]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliMagFCheb.cxx
syst. check that reads the MC information for the case of TPC-only
[u/mrichter/AliRoot.git] / STEER / AliMagFCheb.cxx
1 ///////////////////////////////////////////////////////////////////////////////////
2 //                                                                               //
3 //  Wrapper for the set of mag.field parameterizations by Chebyshev polinomials  //
4 //  To obtain the field in cartesian coordinates/components use                  //
5 //    Field(float* xyz, float* bxyz);                                            //
6 //  For cylindrical coordinates/components:                                      //
7 //    FieldCyl(float* rphiz, float* brphiz)                                      //
8 //                                                                               //
9 //  The solenoid part is parameterized in the volume  R<500, -550<Z<550 cm       //
10 //                                                                               //
11 //  The region R<423 cm,  -343.3<Z<481.3 for 30kA and -343.3<Z<481.3 for 12kA    //
12 //  is parameterized using measured data while outside the Tosca calculation     //
13 //  is used (matched to data on the boundary of the measurements)                //
14 //                                                                               //
15 //  Two options are possible:                                                    //
16 //  1) _BRING_TO_BOUNDARY_ is defined in the AliCheb3D:                          //
17 //     If the querried point is outside of the validity region then the field    //
18 //     at the closest point on the fitted surface is returned.                   //
19 //  2) _BRING_TO_BOUNDARY_ is not defined in the AliCheb3D:                      //
20 //     If the querried point is outside of the validity region the return        //
21 //     value for the field components are set to 0.                              //
22 //                                                                               //
23 //  To obtain the field integral in the TPC region from given point to nearest   //
24 //  cathod plane (+- 250 cm) use:                                                //
25 //  GetTPCInt(float* xyz, float* bxyz);  for Cartesian frame                     //
26 //  or                                                                           //
27 //  GetTPCIntCyl(Float_t *rphiz, Float_t *b); for Cylindrical frame              //
28 //                                                                               //
29 //                                                                               //
30 //  The units are kiloGauss and cm.                                              //
31 //                                                                               //
32 ///////////////////////////////////////////////////////////////////////////////////
33
34 #include "AliMagFCheb.h"
35
36 ClassImp(AliMagFCheb)
37
38 //__________________________________________________________________________________________
39 AliMagFCheb::AliMagFCheb() : 
40   fNParamsSol(0),
41   fNSegZSol(0),
42   fNParamsTPCInt(0),
43   fNSegZTPCInt(0),
44   fNParamsDip(0),
45 //
46   fNZSegDip(0),
47   fNYSegDip(0),
48   fNXSegDip(0),
49 //
50   fSegZSol(0),
51   fSegRSol(0),
52 //
53   fSegZTPCInt(0),
54   fSegRTPCInt(0),
55 //
56   fSegZDip(0),
57   fSegYDip(0),
58   fSegXDip(0),
59 //
60   fNSegRSol(0),
61   fSegZIdSol(0),
62 //
63   fNSegRTPCInt(0),
64   fSegZIdTPCInt(0),
65 //
66   fBegSegYDip(0),
67   fNSegYDip(0),
68   fBegSegXDip(0),
69   fNSegXDip(0),
70   fSegIDDip(0),
71 //
72   fMinZSol(1e6),
73   fMaxZSol(-1e6),
74   fMaxRSol(-1e6), 
75 //
76   fMinZDip(1e6),
77   fMaxZDip(-1e6),
78 //
79   fMinZTPCInt(1e6),
80   fMaxZTPCInt(-1e6),
81   fMaxRTPCInt(-1e6), 
82 //
83   fParamsSol(0),
84   fParamsDip(0),
85   fParamsTPCInt(0)
86 //
87 {}
88
89 //__________________________________________________________________________________________
90 AliMagFCheb::AliMagFCheb(const AliMagFCheb& src) : 
91   TNamed(src),
92   fNParamsSol(0),
93   fNSegZSol(0),
94   fNParamsTPCInt(0),
95   fNSegZTPCInt(0),
96   fNParamsDip(0),
97 //
98   fNZSegDip(0),
99   fNYSegDip(0),
100   fNXSegDip(0),
101 //
102   fSegZSol(0),
103   fSegRSol(0),
104 //
105   fSegZTPCInt(0),
106   fSegRTPCInt(0),
107 //
108   fSegZDip(0),
109   fSegYDip(0),
110   fSegXDip(0),
111 //
112   fNSegRSol(0),
113   fSegZIdSol(0),
114 //
115   fNSegRTPCInt(0),
116   fSegZIdTPCInt(0),
117 //
118   fBegSegYDip(0),
119   fNSegYDip(0),
120   fBegSegXDip(0),
121   fNSegXDip(0),
122   fSegIDDip(0),
123 //
124   fMinZSol(1e6),
125   fMaxZSol(-1e6),
126   fMaxRSol(-1e6), 
127 //
128   fMinZDip(1e6),
129   fMaxZDip(-1e6),
130 //
131   fMinZTPCInt(1e6),
132   fMaxZTPCInt(-1e6),
133   fMaxRTPCInt(-1e6), 
134 //
135   fParamsSol(0),
136   fParamsDip(0),
137   fParamsTPCInt(0)
138 {
139   CopyFrom(src);
140   //
141 }
142
143 //__________________________________________________________________________________________
144 void AliMagFCheb::CopyFrom(const AliMagFCheb& src) 
145
146   Clear();
147   SetName(src.GetName());
148   SetTitle(src.GetTitle());
149   fNParamsSol    = src.fNParamsSol;
150   fNSegZSol      = src.fNSegZSol;
151   fNParamsTPCInt = src.fNParamsTPCInt;
152   fNSegZTPCInt   = src.fNSegZTPCInt; 
153   fNParamsDip    = src.fNParamsDip;
154   //
155   fNZSegDip      = src.fNZSegDip;
156   fNYSegDip      = src.fNYSegDip;
157   fNXSegDip      = src.fNXSegDip;  
158   //
159   fMinZSol       = src.fMinZSol; 
160   fMaxZSol       = src.fMaxZSol;
161   fMaxRSol       = src.fMaxRSol; 
162   //
163   fMinZDip       = src.fMinZDip;
164   fMaxZDip       = src.fMaxZDip;
165   //
166   fMinZTPCInt    = src.fMinZTPCInt;
167   fMaxZTPCInt    = src.fMaxZTPCInt;
168   fMaxRTPCInt    = src.fMaxRTPCInt; 
169   // 
170   if (src.fNParamsSol) {
171     memcpy(fSegZSol  = new Float_t[fNSegZSol], src.fSegZSol, sizeof(Float_t)*fNSegZSol);
172     memcpy(fSegRSol  = new Float_t[fNParamsSol], src.fSegRSol, sizeof(Float_t)*fNParamsSol);
173     memcpy(fNSegRSol = new Int_t[fNSegZSol], src.fNSegRSol, sizeof(Int_t)*fNSegZSol);
174     memcpy(fSegZIdSol= new Int_t[fNSegZSol], src.fSegZIdSol, sizeof(Int_t)*fNSegZSol);
175     fParamsSol       = new TObjArray(fNParamsSol);
176     for (int i=0;i<fNParamsSol;i++) fParamsSol->AddAtAndExpand(new AliCheb3D(*src.GetParamSol(i)),i);
177   }
178   //
179   if (src.fNParamsDip) {
180     memcpy(fSegZDip   = new Float_t[fNZSegDip], src.fSegZDip, sizeof(Float_t)*fNZSegDip);
181     memcpy(fSegYDip   = new Float_t[fNYSegDip], src.fSegYDip, sizeof(Float_t)*fNYSegDip);
182     memcpy(fSegXDip   = new Float_t[fNXSegDip], src.fSegZDip, sizeof(Float_t)*fNXSegDip);
183     memcpy(fBegSegYDip= new Int_t[fNZSegDip], src.fBegSegYDip, sizeof(Int_t)*fNZSegDip);
184     memcpy(fNSegYDip  = new Int_t[fNZSegDip], src.fNSegYDip, sizeof(Int_t)*fNZSegDip);
185     memcpy(fBegSegXDip= new Int_t[fNYSegDip], src.fBegSegXDip, sizeof(Int_t)*fNYSegDip);
186     memcpy(fNSegXDip  = new Int_t[fNYSegDip], src.fNSegXDip, sizeof(Int_t)*fNYSegDip);
187     memcpy(fSegIDDip  = new Int_t[fNXSegDip], src.fSegIDDip, sizeof(Int_t)*fNXSegDip);
188     fParamsDip        = new TObjArray(fNParamsDip);
189     for (int i=0;i<fNParamsDip;i++) fParamsDip->AddAtAndExpand(new AliCheb3D(*src.GetParamDip(i)),i);
190   }
191   //
192   if (src.fNParamsTPCInt) {
193     memcpy(fSegZTPCInt  = new Float_t[fNSegZTPCInt], src.fSegZTPCInt, sizeof(Float_t)*fNSegZTPCInt);
194     memcpy(fSegRTPCInt  = new Float_t[fNParamsTPCInt], src.fSegRTPCInt, sizeof(Float_t)*fNParamsTPCInt);
195     memcpy(fNSegRTPCInt = new Int_t[fNSegZTPCInt], src.fNSegRTPCInt, sizeof(Int_t)*fNSegZTPCInt);
196     memcpy(fSegZIdTPCInt= new Int_t[fNSegZTPCInt], src.fSegZIdTPCInt, sizeof(Int_t)*fNSegZTPCInt);
197     fParamsTPCInt       = new TObjArray(fNParamsTPCInt);
198     for (int i=0;i<fNParamsTPCInt;i++) fParamsTPCInt->AddAtAndExpand(new AliCheb3D(*src.GetParamTPCInt(i)),i);
199   }
200   //
201 }
202
203 //__________________________________________________________________________________________
204 AliMagFCheb& AliMagFCheb::operator=(const AliMagFCheb& rhs)
205 {
206   if (this != &rhs) {  
207     Clear();
208     CopyFrom(rhs);
209   }
210   return *this;  
211   //
212 }
213
214 //__________________________________________________________________________________________
215 void AliMagFCheb::Clear(Option_t *)
216 {
217   if (fNParamsSol) {
218     delete   fParamsSol;
219     delete[] fSegZSol;
220     delete[] fSegRSol;
221     delete[] fNSegRSol;
222     delete[] fSegZIdSol;
223   }
224   //
225   if (fNParamsTPCInt) {
226     delete   fParamsTPCInt;
227     delete[] fSegZTPCInt;
228     delete[] fSegRTPCInt;
229     delete[] fNSegRTPCInt;
230     delete[] fSegZIdTPCInt;
231   }
232   // 
233   if (fNParamsDip) {
234     delete   fParamsDip;
235     delete[] fSegZDip;
236     delete[] fSegYDip;
237     delete[] fSegXDip;
238     delete[] fBegSegYDip;
239     delete[] fNSegYDip;
240     delete[] fBegSegXDip;
241     delete[] fNSegXDip;
242     delete[] fSegIDDip;
243   }
244   fNParamsSol = fNParamsTPCInt = fNParamsDip = fNZSegDip = fNYSegDip = fNXSegDip = 0;
245   fNSegZSol = fNSegZTPCInt = 0;
246   fMinZSol = fMinZDip = fMinZTPCInt = 1e6;
247   fMaxZSol = fMaxZDip = fMaxZTPCInt = fMaxRSol = fMaxRTPCInt = -1e6;
248   //
249 }
250
251 //__________________________________________________________________________________________
252 void AliMagFCheb::Field(Float_t *xyz, Float_t *b) const
253 {
254   // compute field in cartesian coordinates. If point is outside of the parameterized region
255   // get it at closest valid point
256   static float rphiz[3];
257   //
258 #ifndef _BRING_TO_BOUNDARY_  // exact matching to fitted volume is requested
259   if ( !(xyz[2]>=GetMinZSol()&&xyz[2]<=GetMaxZSol()) && 
260        !(xyz[2]>=GetMinZDip()&&xyz[2]<=GetMaxZDip())  ) {for (int i=3;i--;) b[i]=0; return;}
261 #endif
262   //
263   if (xyz[2]<fMaxZDip) {    // dipole part?
264 #ifndef _BRING_TO_BOUNDARY_
265     AliCheb3D* par = GetParamDip(FindDipSegment(xyz));
266     if (par->IsInside(xyz)) {par->Eval(xyz,b); return;}
267     for (int i=3;i--;) b[i]=0; return;
268 #else
269     GetParamDip(FindDipSegment(xyz))->Eval(xyz,b); return;  
270 #endif
271   }
272   //
273   // Sol region: convert coordinates to cyl system
274   CartToCyl(xyz,rphiz);
275 #ifndef _BRING_TO_BOUNDARY_
276   if (rphiz[0]>GetMaxRSol()) {for (int i=3;i--;) b[i]=0; return;}
277 #endif
278   //
279   FieldCylSol(rphiz,b);
280   //
281   // convert field to cartesian system
282   CylToCartCylB(rphiz, b,b);
283   //
284 }
285
286 //__________________________________________________________________________________________
287 void AliMagFCheb::GetTPCInt(Float_t *xyz, Float_t *b) const
288 {
289   // compute TPC region field integral in cartesian coordinates.
290   // If point is outside of the parameterized region get it at closeset valid point
291   static float rphiz[3];
292   //
293   // TPCInt region
294   // convert coordinates to cyl system
295   CartToCyl(xyz,rphiz);
296 #ifndef _BRING_TO_BOUNDARY_
297   if ( (rphiz[2]>GetMaxZTPCInt()||rphiz[2]<GetMinZTPCInt()) ||
298        rphiz[0]>GetMaxRTPCInt()) {for (int i=3;i--;) b[i]=0; return;}
299 #endif
300   //
301   GetTPCIntCyl(rphiz,b);
302   //
303   // convert field to cartesian system
304   CylToCartCylB(rphiz, b,b);
305   //
306 }
307
308 //__________________________________________________________________________________________
309 void AliMagFCheb::FieldCylSol(Float_t *rphiz, Float_t *b) const
310 {
311   // compute Solenoid field in Cylindircal coordinates
312   // note: if the point is outside the volume get the field in closest parameterized point
313   float &r = rphiz[0];
314   float &z = rphiz[2];
315   int SolZId = 0;
316   while (z>fSegZSol[SolZId] && SolZId<fNSegZSol-1) ++SolZId;    // find Z segment
317   int SolRId = fSegZIdSol[SolZId];        // first R segment for this Z
318   int SolRMax = SolRId + fNSegRSol[SolZId];
319   while (r>fSegRSol[SolRId] && SolRId<SolRMax-1) ++SolRId;    // find R segment
320   GetParamSol( SolRId )->Eval(rphiz,b);
321   //
322 }
323
324 //__________________________________________________________________________________________
325 void AliMagFCheb::GetTPCIntCyl(Float_t *rphiz, Float_t *b) const
326 {
327   // compute field integral in TPC region in Cylindircal coordinates
328   // note: the check for the point being inside the parameterized region is done outside
329   float &r = rphiz[0];
330   float &z = rphiz[2];
331   int TPCIntZId = 0;
332   while (z>fSegZTPCInt[TPCIntZId] && TPCIntZId<fNSegZTPCInt) ++TPCIntZId;    // find Z segment
333   int TPCIntRId = fSegZIdTPCInt[TPCIntZId];        // first R segment for this Z
334   int TPCIntRIdMax = TPCIntRId + fNSegRTPCInt[TPCIntZId];
335   while (r>fSegRTPCInt[TPCIntRId] && TPCIntRId<TPCIntRIdMax) ++TPCIntRId;    // find R segment
336   GetParamTPCInt( TPCIntRId )->Eval(rphiz,b);
337   //
338 }
339
340
341 //__________________________________________________________________________________________
342 void AliMagFCheb::Print(Option_t *) const
343 {
344   printf("Alice magnetic field parameterized by Chebyshev polynomials\n");
345   printf("Segmentation for Solenoid (%+.2f<Z<%+.2f cm | R<%.2f cm)\n",fMinZSol,fMaxZSol,fMaxRSol);
346   //
347   if (fParamsSol) fParamsSol->Print();
348   /*
349   for (int iz=0;iz<fNSegZSol;iz++) {
350     AliCheb3D* param = GetParamSol( fSegZIdSol[iz] );
351     printf("*** Z Segment %2d (%+7.2f<Z<%+7.2f)\t***\n",iz,param->GetBoundMin(2),param->GetBoundMax(2));
352     for (int ir=0;ir<fNSegRSol[iz];ir++) {
353       param = GetParamSol( fSegZIdSol[iz]+ir );
354       printf("    R Segment %2d (%+7.2f<R<%+7.2f, Precision: %.1e) (ID=%2d)\n",ir, param->GetBoundMin(0),
355              param->GetBoundMax(0),param->GetPrecision(),fSegZIdSol[iz]+ir);
356     }
357   }
358   */
359   //
360   printf("Segmentation for TPC field integral (%+.2f<Z<%+.2f cm | R<%.2f cm)\n",fMinZTPCInt,fMaxZTPCInt,fMaxRTPCInt);
361   //
362   if (fParamsTPCInt) fParamsTPCInt->Print();
363   /*
364   for (int iz=0;iz<fNSegZTPCInt;iz++) {
365     AliCheb3D* param = GetParamTPCInt( fSegZIdTPCInt[iz] );
366     printf("*** Z Segment %2d (%+7.2f<Z<%+7.2f)\t***\n",iz,param->GetBoundMin(2),param->GetBoundMax(2));
367     for (int ir=0;ir<fNSegRTPCInt[iz];ir++) {
368       param = GetParamTPCInt( fSegZIdTPCInt[iz]+ir );
369       printf("    R Segment %2d (%+7.2f<R<%+7.2f, Precision: %.1e) (ID=%2d)\n",ir, param->GetBoundMin(0),
370              param->GetBoundMax(0),param->GetPrecision(),fSegZIdTPCInt[iz]+ir);
371     }
372   }
373   */
374   //
375   printf("Segmentation for Dipole (%+.2f<Z<%+.2f cm)\n",fMinZDip,fMaxZDip);
376   if (fParamsDip) fParamsDip->Print();
377   //
378   
379
380 }
381 #ifdef  _INC_CREATION_ALICHEB3D_
382 //_______________________________________________
383 void AliMagFCheb::LoadData(const char* inpfile)
384 {
385   // read coefficients data from the text file
386   //
387   TString strf = inpfile;
388   gSystem->ExpandPathName(strf);
389   FILE* stream = fopen(strf,"r");
390   if (!stream) {
391     printf("Did not find input file %s\n",strf.Data());
392     return;
393   }
394   //
395   TString buffs;
396   AliCheb3DCalc::ReadLine(buffs,stream);
397   if (!buffs.BeginsWith("START")) {
398     Error("LoadData","Expected: \"START <name>\", found \"%s\"\nStop\n",buffs.Data());
399     exit(1);
400   }
401   if (buffs.First(' ')>0) SetName(buffs.Data()+buffs.First(' ')+1);
402   //
403   // Solenoid part    -----------------------------------------------------------
404   AliCheb3DCalc::ReadLine(buffs,stream);
405   if (!buffs.BeginsWith("START SOLENOID")) {
406     Error("LoadData","Expected: \"START SOLENOID\", found \"%s\"\nStop\n",buffs.Data());
407     exit(1);
408   }
409   AliCheb3DCalc::ReadLine(buffs,stream); // nparam
410   int nparSol = buffs.Atoi(); 
411   //
412   for (int ip=0;ip<nparSol;ip++) {
413     AliCheb3D* cheb = new AliCheb3D();
414     cheb->LoadData(stream);
415     AddParamSol(cheb);
416   }
417   //
418   AliCheb3DCalc::ReadLine(buffs,stream);
419   if (!buffs.BeginsWith("END SOLENOID")) {
420     Error("LoadData","Expected \"END SOLENOID\", found \"%s\"\nStop\n",buffs.Data());
421     exit(1);
422   }
423   //
424   // TPCInt part     -----------------------------------------------------------
425   AliCheb3DCalc::ReadLine(buffs,stream);
426   if (!buffs.BeginsWith("START TPCINT")) {
427     Error("LoadData","Expected: \"START TPCINT\", found \"%s\"\nStop\n",buffs.Data());
428     exit(1);
429   }
430   AliCheb3DCalc::ReadLine(buffs,stream); // nparam
431   int nparTPCInt = buffs.Atoi(); 
432   //
433   for (int ip=0;ip<nparTPCInt;ip++) {
434     AliCheb3D* cheb = new AliCheb3D();
435     cheb->LoadData(stream);
436     AddParamTPCInt(cheb);
437   }
438   //
439   AliCheb3DCalc::ReadLine(buffs,stream);
440   if (!buffs.BeginsWith("END TPCINT")) {
441     Error("LoadData","Expected \"END TPCINT\", found \"%s\"\nStop\n",buffs.Data());
442     exit(1);
443   }
444   //
445   // Dipole part    -----------------------------------------------------------
446   AliCheb3DCalc::ReadLine(buffs,stream);
447   if (!buffs.BeginsWith("START DIPOLE")) {
448     Error("LoadData","Expected: \"START DIPOLE\", found \"%s\"\nStop\n",buffs.Data());
449     exit(1);
450   }
451   AliCheb3DCalc::ReadLine(buffs,stream); // nparam
452   int nparDip = buffs.Atoi();  
453   //
454   for (int ip=0;ip<nparDip;ip++) {
455     AliCheb3D* cheb = new AliCheb3D();
456     cheb->LoadData(stream);
457     AddParamDip(cheb);
458   }
459   //
460   AliCheb3DCalc::ReadLine(buffs,stream);
461   if (!buffs.BeginsWith("END DIPOLE")) {
462     Error("LoadData","Expected \"END DIPOLE\", found \"%s\"\nStop\n",GetName(),buffs.Data());
463     exit(1);
464   }
465   //
466   AliCheb3DCalc::ReadLine(buffs,stream);
467   if (!buffs.BeginsWith("END") || !buffs.Contains(GetName())) {
468     Error("LoadData","Expected: \"END %s\", found \"%s\"\nStop\n",GetName(),buffs.Data());
469     exit(1);
470   }
471   //
472   // ---------------------------------------------------------------------------
473   fclose(stream);
474   BuildTableSol();
475   BuildTableTPCInt();
476   BuildTableDip();
477   printf("Loaded magnetic field \"%s\" from %s\n",GetName(),strf.Data());
478   //
479 }
480 #endif
481
482 //_________________________________________________________________________
483 Int_t AliMagFCheb::FindDipSegment(float *xyz) const
484 {
485   // find the segment containing point xyz. If it is outside find the closest segment 
486   int xid,yid,zid = TMath::BinarySearch(fNZSegDip,fSegZDip,xyz[2]); // find zsegment
487   int ysegBeg = fBegSegYDip[zid];
488   //
489   for (yid=0;yid<fNSegYDip[zid];yid++) if (xyz[1]<fSegYDip[ysegBeg+yid]) break;
490   if ( --yid < 0 ) yid = 0;
491   yid +=  ysegBeg;
492   //
493   int xsegBeg = fBegSegXDip[yid];
494   for (xid=0;xid<fNSegXDip[yid];xid++) if (xyz[0]<fSegXDip[xsegBeg+xid]) break;
495   if ( --xid < 0) xid = 0;
496   xid +=  xsegBeg;
497   //
498   return fSegIDDip[xid];
499 }
500
501 //_______________________________________________
502 #ifdef  _INC_CREATION_ALICHEB3D_
503
504
505 //__________________________________________________________________________________________
506 AliMagFCheb::AliMagFCheb(const char* inputFile) : 
507   fNParamsSol(0),
508   fNSegZSol(0),
509   fNParamsTPCInt(0),
510   fNSegZTPCInt(0),
511   fNParamsDip(0),
512 //
513   fNZSegDip(0),
514   fNYSegDip(0),
515   fNXSegDip(0),
516 //
517   fSegZSol(0),
518   fSegRSol(0),
519 //
520   fSegZTPCInt(0),
521   fSegRTPCInt(0),
522 //
523   fSegZDip(0),
524   fSegYDip(0),
525   fSegXDip(0),
526 //
527   fNSegRSol(0),
528   fSegZIdSol(0),
529 //
530   fNSegRTPCInt(0),
531   fSegZIdTPCInt(0),
532 //
533   fBegSegYDip(0),
534   fNSegYDip(0),
535   fBegSegXDip(0),
536   fNSegXDip(0),
537   fSegIDDip(0),
538 //
539   fMinZSol(0),
540   fMaxZSol(0),
541   fMaxRSol(0), 
542 //
543   fMinZDip(0),
544   fMaxZDip(0),
545 //
546   fMinZTPCInt(0),
547   fMaxZTPCInt(0),
548   fMaxRTPCInt(0), 
549 //
550   fParamsSol(0),
551   fParamsDip(0),
552   fParamsTPCInt(0)
553 //
554 //
555 {
556   LoadData(inputFile);
557 }
558
559 //__________________________________________________________________________________________
560 void AliMagFCheb::AddParamSol(AliCheb3D* param)
561 {
562   // adds new parameterization piece for Sol
563   // NOTE: pieces must be added strictly in increasing R then increasing Z order
564   //
565   if (!fParamsSol) fParamsSol = new TObjArray();
566   fParamsSol->Add(param);
567   fNParamsSol++;
568   //
569 }
570
571 //__________________________________________________________________________________________
572 void AliMagFCheb::AddParamTPCInt(AliCheb3D* param)
573 {
574   // adds new parameterization piece for TPCInt
575   // NOTE: pieces must be added strictly in increasing R then increasing Z order
576   //
577   if (!fParamsTPCInt) fParamsTPCInt = new TObjArray();
578   fParamsTPCInt->Add(param);
579   fNParamsTPCInt++;
580   //
581 }
582
583 //__________________________________________________________________________________________
584 void AliMagFCheb::AddParamDip(AliCheb3D* param)
585 {
586   // adds new parameterization piece for Dipole
587   //
588   if (!fParamsDip) fParamsDip = new TObjArray();
589   fParamsDip->Add(param);
590   fNParamsDip++;
591   //
592 }
593
594 //__________________________________________________________________________________________
595 void AliMagFCheb::ResetTPCInt()
596 {
597   // clean TPC field integral (used for update)
598   if (!fNParamsTPCInt) return;
599   delete fParamsTPCInt;  
600   delete[] fSegZTPCInt;
601   delete[] fSegRTPCInt;
602   delete[] fNSegRTPCInt;
603   delete[] fSegZIdTPCInt;
604   //
605   fNParamsTPCInt = 0; 
606   fNSegZTPCInt   = 0;
607   fSegZTPCInt    = 0; 
608   fSegRTPCInt    = 0; 
609   fNSegRTPCInt   = 0; 
610   fSegZIdTPCInt  = 0;
611   fMinZTPCInt    = 0; 
612   fMaxZTPCInt    = 0; 
613   fMaxRTPCInt    = 0; 
614   fParamsTPCInt  = 0;
615   //
616 }
617
618 //__________________________________________________
619 void AliMagFCheb::BuildTableDip()
620 {
621   //
622   TArrayF segY,segX;
623   TArrayI begSegYDip,begSegXDip;
624   TArrayI nsegYDip,nsegXDip;
625   TArrayI segID;
626   float *tmpSegZ,*tmpSegY,*tmpSegX;
627   //
628   // create segmentation in Z
629   fNZSegDip = SegmentDipDimension(&tmpSegZ, fParamsDip, fNParamsDip, 2, 1,-1, 1,-1, 1,-1) - 1;
630   fNYSegDip = 0;
631   fNXSegDip = 0;
632   //
633   // for each Z slice create segmentation in Y
634   begSegYDip.Set(fNZSegDip);
635   nsegYDip.Set(fNZSegDip);
636   float xyz[3];
637   for (int iz=0;iz<fNZSegDip;iz++) {
638     printf("\nZSegment#%d  %+e : %+e\n",iz,tmpSegZ[iz],tmpSegZ[iz+1]);
639     int ny = SegmentDipDimension(&tmpSegY, fParamsDip, fNParamsDip, 1, 
640                                  1,-1, 1,-1, tmpSegZ[iz],tmpSegZ[iz+1]) - 1;
641     segY.Set(ny + fNYSegDip);
642     for (int iy=0;iy<ny;iy++) segY[fNYSegDip+iy] = tmpSegY[iy];
643     begSegYDip[iz] = fNYSegDip;
644     nsegYDip[iz] = ny;
645     printf(" Found %d YSegments, to start from %d\n",ny, begSegYDip[iz]);
646     //
647     // for each slice in Z and Y create segmentation in X
648     begSegXDip.Set(fNYSegDip+ny);
649     nsegXDip.Set(fNYSegDip+ny);
650     xyz[2] = (tmpSegZ[iz]+tmpSegZ[iz+1])/2.; // mean Z of this segment
651     //
652     for (int iy=0;iy<ny;iy++) {
653       int isg = fNYSegDip+iy;
654       printf("\n   YSegment#%d  %+e : %+e\n",iy, tmpSegY[iy],tmpSegY[iy+1]);
655       int nx = SegmentDipDimension(&tmpSegX, fParamsDip, fNParamsDip, 0, 
656                                    1,-1, tmpSegY[iy],tmpSegY[iy+1], tmpSegZ[iz],tmpSegZ[iz+1]) - 1;
657       //
658       segX.Set(nx + fNXSegDip);
659       for (int ix=0;ix<nx;ix++) segX[fNXSegDip+ix] = tmpSegX[ix];
660       begSegXDip[isg] = fNXSegDip;
661       nsegXDip[isg] = nx;
662       printf("   Found %d XSegments, to start from %d\n",nx, begSegXDip[isg]);
663       //
664       segID.Set(fNXSegDip+nx);
665       //
666       // find corresponding params
667       xyz[1] = (tmpSegY[iy]+tmpSegY[iy+1])/2.; // mean Y of this segment
668       //
669       for (int ix=0;ix<nx;ix++) {
670         xyz[0] = (tmpSegX[ix]+tmpSegX[ix+1])/2.; // mean X of this segment
671         for (int ipar=0;ipar<fNParamsDip;ipar++) {
672           AliCheb3D* cheb = (AliCheb3D*) fParamsDip->At(ipar);
673           if (!cheb->IsInside(xyz)) continue;
674           segID[fNXSegDip+ix] = ipar;
675           break;
676         }
677       }
678       fNXSegDip += nx;
679       //
680       delete[] tmpSegX;
681     }
682     delete[] tmpSegY;
683     fNYSegDip += ny;
684   }
685   //
686   fMinZDip = tmpSegZ[0];
687   fMaxZDip = tmpSegZ[fNZSegDip];
688   fSegZDip    = new Float_t[fNZSegDip];
689   for (int i=fNZSegDip;i--;) fSegZDip[i] = tmpSegZ[i];
690   delete[] tmpSegZ;
691   //
692   fSegYDip    = new Float_t[fNYSegDip];
693   fSegXDip    = new Float_t[fNXSegDip];
694   fBegSegYDip = new Int_t[fNZSegDip];
695   fNSegYDip   = new Int_t[fNZSegDip];
696   fBegSegXDip = new Int_t[fNYSegDip];
697   fNSegXDip   = new Int_t[fNYSegDip];
698   fSegIDDip   = new Int_t[fNXSegDip];
699   //
700   for (int i=fNYSegDip;i--;) fSegYDip[i] = segY[i];
701   for (int i=fNXSegDip;i--;) fSegXDip[i] = segX[i];
702   for (int i=fNZSegDip;i--;) {fBegSegYDip[i] = begSegYDip[i]; fNSegYDip[i] = nsegYDip[i];}
703   for (int i=fNYSegDip;i--;) {fBegSegXDip[i] = begSegXDip[i]; fNSegXDip[i] = nsegXDip[i];}
704   for (int i=fNXSegDip;i--;) {fSegIDDip[i]   = segID[i];}
705   //
706 }
707
708 //__________________________________________________________________________________________
709 void AliMagFCheb::BuildTableSol()
710 {
711   // build the indexes for each parameterization of Solenoid
712   //
713   const float kSafety=0.001;
714   //
715   if (fNParamsSol<1) return;
716   fSegRSol   = new Float_t[fNParamsSol];
717   float *tmpbufF  = new float[fNParamsSol+1];
718   int   *tmpbufI  = new int[fNParamsSol+1];
719   int   *tmpbufI1 = new int[fNParamsSol+1];
720   //
721   // count number of Z slices and number of R slices in each Z slice
722   for (int ip=0;ip<fNParamsSol;ip++) {
723     if (ip==0 || (GetParamSol(ip)->GetBoundMax(2)-GetParamSol(ip-1)->GetBoundMax(2))>kSafety) { // new Z slice
724       tmpbufF[fNSegZSol] = GetParamSol(ip)->GetBoundMax(2);                                     // 
725       tmpbufI[fNSegZSol] = 0;
726       tmpbufI1[fNSegZSol++] = ip;
727     }
728     fSegRSol[ip] = GetParamSol(ip)->GetBoundMax(0);  // upper R
729     tmpbufI[fNSegZSol-1]++;
730   }
731   //
732   fSegZSol   = new Float_t[fNSegZSol];
733   fSegZIdSol = new Int_t[fNSegZSol];
734   fNSegRSol  = new Int_t[fNSegZSol];
735   for (int iz=0;iz<fNSegZSol;iz++) {
736     fSegZSol[iz]   = tmpbufF[iz];
737     fNSegRSol[iz]  = tmpbufI[iz];
738     fSegZIdSol[iz] = tmpbufI1[iz];
739   }
740   //
741   fMinZSol = GetParamSol(0)->GetBoundMin(2);
742   fMaxZSol = GetParamSol(fNParamsSol-1)->GetBoundMax(2);
743   fMaxRSol = GetParamSol(fNParamsSol-1)->GetBoundMax(0);
744   //
745   delete[] tmpbufF;
746   delete[] tmpbufI;
747   delete[] tmpbufI1;
748   //
749   //
750 }
751
752 //__________________________________________________________________________________________
753 void AliMagFCheb::BuildTableTPCInt()
754 {
755   // build the indexes for each parameterization of TPC field integral
756   //
757   const float kSafety=0.001;
758   //
759   if (fNParamsTPCInt<1) return;
760   fSegRTPCInt   = new Float_t[fNParamsTPCInt];
761   float *tmpbufF  = new float[fNParamsTPCInt+1];
762   int   *tmpbufI  = new int[fNParamsTPCInt+1];
763   int   *tmpbufI1 = new int[fNParamsTPCInt+1];
764   //
765   // count number of Z slices and number of R slices in each Z slice
766   for (int ip=0;ip<fNParamsTPCInt;ip++) {
767     if (ip==0 || (GetParamTPCInt(ip)->GetBoundMax(2)-GetParamTPCInt(ip-1)->GetBoundMax(2))>kSafety) { // new Z slice
768       tmpbufF[fNSegZTPCInt] = GetParamTPCInt(ip)->GetBoundMax(2);                                     // 
769       tmpbufI[fNSegZTPCInt] = 0;
770       tmpbufI1[fNSegZTPCInt++] = ip;
771     }
772     fSegRTPCInt[ip] = GetParamTPCInt(ip)->GetBoundMax(0);  // upper R
773     tmpbufI[fNSegZTPCInt-1]++;
774   }
775   //
776   fSegZTPCInt   = new Float_t[fNSegZTPCInt];
777   fSegZIdTPCInt = new Int_t[fNSegZTPCInt];
778   fNSegRTPCInt  = new Int_t[fNSegZTPCInt];
779   for (int iz=0;iz<fNSegZTPCInt;iz++) {
780     fSegZTPCInt[iz]   = tmpbufF[iz];
781     fNSegRTPCInt[iz]  = tmpbufI[iz];
782     fSegZIdTPCInt[iz] = tmpbufI1[iz];
783   }
784   //
785   fMinZTPCInt = GetParamTPCInt(0)->GetBoundMin(2);
786   fMaxZTPCInt = GetParamTPCInt(fNParamsTPCInt-1)->GetBoundMax(2);
787   fMaxRTPCInt = GetParamTPCInt(fNParamsTPCInt-1)->GetBoundMax(0);
788   //
789   delete[] tmpbufF;
790   delete[] tmpbufI;
791   delete[] tmpbufI1;
792   //
793   //
794 }
795
796 void AliMagFCheb::SaveData(const char* outfile) const
797 {
798   // writes coefficients data to output text file
799   TString strf = outfile;
800   gSystem->ExpandPathName(strf);
801   FILE* stream = fopen(strf,"w+");
802   //
803   // Sol part    ---------------------------------------------------------
804   fprintf(stream,"# Set of Chebyshev parameterizations for ALICE magnetic field\nSTART %s\n",GetName());
805   fprintf(stream,"START SOLENOID\n#Number of pieces\n%d\n",fNParamsSol);
806   for (int ip=0;ip<fNParamsSol;ip++) GetParamSol(ip)->SaveData(stream);
807   fprintf(stream,"#\nEND SOLENOID\n");
808   //
809   // TPCInt part ---------------------------------------------------------
810   fprintf(stream,"# Set of Chebyshev parameterizations for ALICE magnetic field\nSTART %s\n",GetName());
811   fprintf(stream,"START TPCINT\n#Number of pieces\n%d\n",fNParamsTPCInt);
812   for (int ip=0;ip<fNParamsTPCInt;ip++) GetParamTPCInt(ip)->SaveData(stream);
813   fprintf(stream,"#\nEND TPCINT\n");
814   //
815   // Dip part   ---------------------------------------------------------
816   fprintf(stream,"START DIPOLE\n#Number of pieces\n%d\n",fNParamsDip);
817   for (int ip=0;ip<fNParamsDip;ip++) GetParamDip(ip)->SaveData(stream);
818   fprintf(stream,"#\nEND DIPOLE\n");
819   //
820   fprintf(stream,"#\nEND %s\n",GetName());
821   //
822   fclose(stream);
823   //
824 }
825
826 Int_t AliMagFCheb::SegmentDipDimension(float** seg,const TObjArray* par,int npar, int dim, 
827                                        float xmn,float xmx,float ymn,float ymx,float zmn,float zmx)
828 {
829   // find all boundaries in deimension dim for boxes in given region.
830   // if mn>mx for given projection the check is not done for it.
831   float *tmpC = new float[2*npar];
832   int *tmpInd = new int[2*npar];
833   int nseg0 = 0;
834   for (int ip=0;ip<npar;ip++) {
835     AliCheb3D* cheb = (AliCheb3D*) par->At(ip);
836     if (xmn<xmx && (cheb->GetBoundMin(0)>(xmx+xmn)/2 || cheb->GetBoundMax(0)<(xmn+xmx)/2)) continue;
837     if (ymn<ymx && (cheb->GetBoundMin(1)>(ymx+ymn)/2 || cheb->GetBoundMax(1)<(ymn+ymx)/2)) continue;
838     if (zmn<zmx && (cheb->GetBoundMin(2)>(zmx+zmn)/2 || cheb->GetBoundMax(2)<(zmn+zmx)/2)) continue;
839     //
840     tmpC[nseg0++] = cheb->GetBoundMin(dim);
841     tmpC[nseg0++] = cheb->GetBoundMax(dim);    
842   }
843   // range Dim's boundaries in increasing order
844   TMath::Sort(nseg0,tmpC,tmpInd,kFALSE);
845   // count number of really different Z's
846   int nseg = 0;
847   float cprev = -1e6;
848   for (int ip=0;ip<nseg0;ip++) {
849     if (TMath::Abs(cprev-tmpC[ tmpInd[ip] ])>1e-4) {
850       cprev = tmpC[ tmpInd[ip] ];
851       nseg++;
852     }
853     else tmpInd[ip] = -1; // supress redundant Z
854   }
855   // 
856   *seg  = new float[nseg]; // create final Z segmenations
857   nseg = 0;
858   for (int ip=0;ip<nseg0;ip++) if (tmpInd[ip]>=0) (*seg)[nseg++] = tmpC[ tmpInd[ip] ];
859   //
860   delete[] tmpC;
861   delete[] tmpInd;
862   return nseg;
863 }
864
865 #endif
866