]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/AliSurveyObj.cxx
Added method GetDeltaForBranch getting the delta transformation, for a sensitive...
[u/mrichter/AliRoot.git] / STEER / AliSurveyObj.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /////////////////////////////////////////////////////////////////////
17 //                                                                 //
18 //  class AliSurveyObj                                             //
19 //  Retrieve and Convert survey data into ROOT Objects             //
20 //                                                                 //
21 /////////////////////////////////////////////////////////////////////
22
23 #include "AliSurveyObj.h"
24
25 //ROOT includes
26 #include "TROOT.h"
27 #include "Riostream.h"
28 #include "TObjArray.h"
29 #include "TGrid.h"
30 #include "TGridResult.h"
31 #include "TFile.h"
32 #include "TObjString.h"
33
34 //AliROOT includes
35 #include "AliLog.h"
36
37 ClassImp(AliSurveyObj)
38
39
40 const TString AliSurveyObj::fgkStorage = "alien://alice.cern.ch";  
41 const TString AliSurveyObj::fgkBaseFolder = "/alice/data/Reference";
42 const TString AliSurveyObj::fgkValidDetectors = "ACORDE,BABYFRAME,BACKFRAME,\
43 EMCAL,FMD,HMPID,ITS,L3 MAGNET,MUON,MUON ABSORBERS,MUON DIPOLE,PHOS,PMD,\
44 SPACEFRAME,SUPERSTRUCTURE,T0,TOF,TPC,TRD,V0,ZDC,GRP";
45 const TString AliSurveyObj::fgkGRPDetectors = "BABYFRAME,BACKFRAME,L3 MAGNET,\
46 SPACEFRAME,MUON DIPOLE,MUON ABSORBERS,GRP";
47 const TString AliSurveyObj::fgkMUONDetectors = "MUON,SUPERSTRUCTURE";
48
49   
50 //_____________________________________________________________________________
51 AliSurveyObj::AliSurveyObj():
52   TObject(),
53   fTitle(""),
54   fDate(""),
55   fDetector(""),
56   fURL("http://edms.cern.ch/"),
57   fReportNr(-1),
58   fVersion(-1),
59   fObs(""),
60   fCoordSys(""),
61   fUnits(""),
62   fNrColumns(-1),
63   fColNames(""),
64   fIsValid(kFALSE),
65   fGridUser(""),
66   fDataPoints(new TObjArray(1))
67 {
68   // constructor
69   fDataPoints->SetOwner(kTRUE);
70 }
71
72
73 //_____________________________________________________________________________
74 AliSurveyObj::~AliSurveyObj() {
75   //destructor
76   if (fDataPoints) {
77     fDataPoints->Delete();
78     fDataPoints = 0;
79   }
80 }
81
82
83 //_____________________________________________________________________________
84 AliSurveyObj::AliSurveyObj(const AliSurveyObj& surveyObj):
85   TObject(),
86   fTitle(surveyObj.fTitle),
87   fDate(surveyObj.fDate),
88   fDetector(surveyObj.fDetector),
89   fURL(surveyObj.fURL),
90   fReportNr(surveyObj.fReportNr),
91   fVersion(surveyObj.fVersion),
92   fObs(surveyObj.fObs),
93   fCoordSys(surveyObj.fCoordSys),
94   fUnits(surveyObj.fUnits),
95   fNrColumns(surveyObj.fNrColumns),
96   fColNames(surveyObj.fColNames),
97   fIsValid(surveyObj.fIsValid),
98   fGridUser(surveyObj.fGridUser),
99   fDataPoints(new TObjArray(1))
100 {
101   // copy constructor
102   TObject *curr = surveyObj.fDataPoints->First();
103   while (curr != 0) {
104     fDataPoints->Add(curr);
105     curr = surveyObj.fDataPoints->After(curr);
106   }
107 }
108
109
110 //_____________________________________________________________________________
111 AliSurveyObj& AliSurveyObj::operator=(const AliSurveyObj& surveyObj)
112 {
113   // assignment operator
114   if (this != &surveyObj) {
115     fTitle = surveyObj.fTitle;
116     fDate = surveyObj.fDate;
117     fDetector = surveyObj.fDetector;
118     fURL = surveyObj.fURL;
119     fReportNr = surveyObj.fReportNr;
120     fVersion = surveyObj.fVersion;
121     fObs = surveyObj.fObs;
122     fCoordSys = surveyObj.fCoordSys;
123     fUnits = surveyObj.fUnits;
124     fNrColumns = surveyObj.fNrColumns;
125     fColNames = surveyObj.fColNames;
126     fIsValid = surveyObj.fIsValid;
127     fGridUser = surveyObj.fGridUser;
128     TObject *curr = surveyObj.fDataPoints->First();
129     while (curr != 0) {
130       fDataPoints->Add(curr);
131       curr = surveyObj.fDataPoints->After(curr);
132     }
133   }
134   return *this;
135 }
136
137
138 //_____________________________________________________________________________
139 void AliSurveyObj::AddPoint(AliSurveyPoint* point) {
140   // Adds a point to the TObjArray which containst the list of points
141   fDataPoints->Add(point);
142   return;
143 }
144
145
146 //_____________________________________________________________________________
147 Bool_t AliSurveyObj::Connect(const char *gridUrl, const char *user) {
148   // Connects to the grid
149
150   // If the same "Grid" is alreay active, skip connection
151   if (!gGrid || gridUrl != gGrid->GridUrl() ||
152       (( user != "" ) && ( user != gGrid->GetUser() )) ) {
153     // connection to the Grid
154     AliInfo("\nConnecting to the Grid...");
155     if (gGrid) {
156       AliInfo(Form("gGrid = %x; GridUrl = %s; gGrid->GridUrl() = %s", 
157                    gGrid, gridUrl, gGrid->GridUrl()));
158       AliInfo(Form("User = %s; gGrid->GetUser() = %s",
159                    user, gGrid->GetUser()));
160     }
161     TGrid::Connect(gridUrl,user);
162   }
163         
164   if(!gGrid) {
165     AliError("Connection failed!");
166     return kFALSE;
167   }
168   return kTRUE;
169 }
170
171
172 //_____________________________________________________________________________
173 Bool_t AliSurveyObj::OpenFile(TString openString) {
174   // Opens the file and reads it to a buffer
175
176   Printf("Open string: \n -> \"%s\"\n", openString.Data());
177
178   if (openString.BeginsWith("alien://"))
179     if (!Connect(fgkStorage.Data(), fGridUser.Data())) {
180       AliError(Form("Error connecting to GRID"));
181       return kFALSE;
182     }
183
184   TFile *file = TFile::Open(openString.Data(), "READ");
185   if ( !file ) {
186     AliError(Form("Error opening file \"%s\"", openString.Data()));
187     return kFALSE;
188   }
189
190   Int_t size = file->GetSize();
191
192   char *buf = new Char_t[size + 1];
193   memset(buf, '\0', size + 1);
194
195   file->Seek(0);  
196   if ( file->ReadBuffer(buf, size) ) {
197     AliError("Error reading file contents to buffer!");
198     return kFALSE;
199   }
200   Printf("%d bytes read!\n", file->GetBytesRead());
201   
202   ParseBuffer(buf);
203
204   file->Close();
205   delete[] buf;
206   return kTRUE;
207 }
208
209
210 //_____________________________________________________________________________
211 Bool_t AliSurveyObj::FillFromLocalFile(const Char_t* filename) {
212   // Fills the object from a file in a local filesystem
213
214   TString fullOpenString = "file://" + TString(filename) + "?filetype=raw";
215
216   return OpenFile(fullOpenString);
217 }
218
219
220 //_____________________________________________________________________________
221 Bool_t AliSurveyObj::IsValidDetector(TString detector) const {
222   // Checks if the detector name is valid
223
224   detector.ToUpper();
225
226   TObjArray *dets = fgkValidDetectors.Tokenize(',');
227   TObject *found = dets->FindObject(detector);
228   dets->Delete();
229   dets = 0;
230
231   if (!found) return kFALSE;
232   else return kTRUE;
233 }
234
235
236 //_____________________________________________________________________________
237 TString AliSurveyObj::RealFolderName(TString detector) const {
238   // Returns the actual folder name for a given detector 
239   // Some "detectors" don't have a folder of their own
240
241   detector.ToUpper();
242   TString folderName = detector;
243
244   TObjArray *dets = fgkGRPDetectors.Tokenize(',');
245   if (dets->FindObject(detector)) folderName = "GRP";
246   dets->Delete();
247   dets = 0;
248
249   dets = fgkMUONDetectors.Tokenize(',');
250   if (dets->FindObject(detector)) folderName = "MUON";
251   dets->Delete();  
252  
253
254
255   dets = 0;
256
257   return folderName;
258 }
259
260 //_____________________________________________________________________________
261 Bool_t AliSurveyObj::Fill(TString detector, Int_t reportNumber,
262                           TString username) {
263   // Fills the object from a file in the default storage location in AliEn.
264   // The highest version available is selected.
265
266   return Fill(detector, reportNumber, -1, username);
267 }
268
269 //_____________________________________________________________________________
270 Bool_t AliSurveyObj::Fill(TString detector, Int_t reportNumber,
271                           Int_t reportVersion, TString username) {
272   // Fills the object from a file in the default storage location in AliEn.
273   // A specific version is selected.
274
275   detector.ToUpper();
276   
277   // Check if <detector> is valid
278   if (!IsValidDetector(detector)) {
279     AliWarning(Form("Detector '%s' is not a valid detector/structure!", detector.Data()));
280     return kFALSE;
281   }
282
283   // Some "detectors" don't have a folder of their own
284   // TString detectorFolder = RealFolderName(detector);
285
286   // Check if <year>, <reportNumber> and <reportVersion> are valid (roughly)
287   if ((reportNumber < 1) || (reportVersion < -1) || (0 == reportVersion)) {
288     AliError("Invalid parameter values for AliSurveyObj::Fill. (Report Number or Report Version)");
289     return kFALSE;
290   }
291
292   // Check if the fGridUser is set, or specified
293   if (username.Length() > 0) SetGridUser(username);
294   else if (0 == fGridUser.Length()) {
295     AliError("GRID username not specified and not previously set!");
296     return kFALSE;
297   }
298
299   // Query AliEn for the available reports
300   TGridResult *res = QueryReports(detector, -1, reportNumber, reportVersion);
301   if (!res) AliError(Form("Error querying AliEn for detector '%s', \
302                            report number '%d' and report version '%d'.",
303                           detector.Data(), reportNumber, reportVersion));
304   Int_t numberEntries = res->GetEntries();
305   if (0 == numberEntries) {
306     AliError(Form("No report found for detector '%s', report number '%d' and report version '%d'",
307                   detector.Data(), reportNumber, reportVersion));
308     return kFALSE;
309   }
310
311   TString fileNamePath = "";
312   if (1 == numberEntries) fileNamePath = res->GetFileNamePath(0);
313   else if (numberEntries > 1) {
314     TString higherVerFNP = res->GetFileNamePath(0);
315     Int_t lastYear = FileNamePathToReportYear(higherVerFNP);
316     for (Int_t i = 1; i < numberEntries; ++i) {
317       TString currFNP = res->GetFileNamePath(i);
318       if (FileNamePathToReportVersion(currFNP) >
319           FileNamePathToReportVersion(higherVerFNP)) higherVerFNP = currFNP;
320       if (lastYear != FileNamePathToReportYear(currFNP))
321         AliWarning("Inconsistency detected, year differs for reports with the same report number! Please inform the responsible and check the report against the one in DCDB.");
322     }
323     fileNamePath = higherVerFNP;
324   }
325
326   TString fullOpenString = "alien://" + fileNamePath + "?filetype=raw";
327   /*
328   // Finally composes the full string
329   TString fullOpenString = "alien://" + fgkBaseFolder + "/" + detectorFolder + "/RawSurvey/";
330   fullOpenString += Form("%d/%d_v%d.txt?filetype=raw", year, reportNumber, reportVersion);
331   */
332
333   return OpenFile(fullOpenString);
334 }
335
336
337 //_____________________________________________________________________________
338 TString AliSurveyObj::FileNamePathToDetector(TString filename) const {
339   // Get the report number from the complete path in the format:
340   // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt
341
342   TString ret = "";
343
344   if (filename.Length() > fgkBaseFolder.Length()) {
345     ret = filename.Remove(0, fgkBaseFolder.Length());
346     ret.Remove(TString::kLeading, '/');
347     ret = ret(0, ret.First('/'));
348     if (!IsValidDetector(ret)) ret = "";
349   } 
350   return ret;
351 }
352
353 ///alice/cern.ch/user/r/rsilva/TRD/RawSurvey/2007/.816582_v2.txt/v1.0
354
355 //_____________________________________________________________________________
356 Int_t AliSurveyObj::FileNamePathToReportYear(TString filename) const {
357   // Get the report year from the complete path in the format:
358   // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt
359
360   TString ret = "";
361
362   if (filename.Length() > fgkBaseFolder.Length()) {
363     ret = filename.Remove(0, fgkBaseFolder.Length());
364     ret.Remove(TString::kLeading, '/');
365     Int_t beg = ret.First('/') + TString("RawSurvey/").Length() + 1;
366     ret = ret(beg, ret.Last('/') - beg);
367     return ret.Atoi();
368   } 
369   return -1;
370 }
371
372
373 //_____________________________________________________________________________
374 Int_t AliSurveyObj::FileNamePathToReportNumber(TString filename) const {
375   // Get the report number from the complete path in the format:
376   // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt
377
378   TString ret = "";
379
380   if (filename.Length() > fgkBaseFolder.Length()) {
381     ret = filename.Remove(0, fgkBaseFolder.Length());
382     ret.Remove(TString::kLeading, '/');
383     if ((ret.CountChar('/') > 3) || (ret.CountChar('.') > 1)) {
384       AliWarning("Error getting the Report Number from the filename path!");
385       return -1;
386     }
387     ret = ret(ret.Last('/') + 1 , ret.Last('_') - ret.Last('/') - 1);
388     return ret.Atoi();
389   } 
390   AliWarning("Error getting the Report Number from the filename path!");
391   return -1;
392 }
393
394
395 //_____________________________________________________________________________
396 Int_t AliSurveyObj::FileNamePathToReportVersion(TString filename) const {
397   // Get the report version from the complete path in the format:
398   // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt
399
400   TString ret = "";
401
402   if (filename.Length() > fgkBaseFolder.Length()) {
403     ret = filename.Remove(0, fgkBaseFolder.Length());
404     ret.Remove(TString::kLeading, '/');
405     if ((ret.CountChar('/') > 3) || (ret.CountChar('.') > 1)) {
406       AliWarning("Error getting the Report Version from the filename path!");
407       return -1;
408     }
409     ret = ret(ret.Last('_') + 1 + 1 , ret.Last('.') - ret.Last('_') - 1 - 1);
410     return ret.Atoi();
411   } 
412   AliWarning("Error getting the Report Version from the filename path!");
413   return -1;
414 }
415
416
417 //_____________________________________________________________________________
418 void AliSurveyObj::ListValidDetectors() {
419   // List the valid detector names
420   Printf("");
421   Printf("Listing all valid detectors:\n");
422   TObjArray *dets = fgkValidDetectors.Tokenize(',');
423   for (int i = 0; i < dets->GetEntries(); ++i) 
424     Printf("%s", ((TObjString *) dets->At(i))->GetString().Data());
425   dets->Delete();
426   dets = 0;
427   Printf("");
428   Printf("Some reports are stored in more general folders.");
429   Printf("These reports can be opened using either name, the original or the");
430   Printf("folder name. Example: 'SPACEFRAME' or 'GRP' are both valid when");
431   Printf("opening a report for the Spaceframe.");
432   Printf("");
433   Printf("Detectors stored in 'MUON' folder:");
434   dets = fgkMUONDetectors.Tokenize(',');
435   for (int i = 0; i < dets->GetEntries(); ++i) 
436     Printf("%s", ((TObjString *) dets->At(i))->GetString().Data());
437   dets->Delete();
438   dets = 0;
439   Printf("");
440   Printf("Detectors stored in 'GRP' folder:");
441   dets = fgkGRPDetectors.Tokenize(',');
442   for (int i = 0; i < dets->GetEntries(); ++i) 
443     Printf("%s", ((TObjString *) dets->At(i))->GetString().Data());
444   dets->Delete();
445   dets = 0;
446   return;
447 }
448
449
450 //_____________________________________________________________________________
451 TGridResult * AliSurveyObj::QueryReports(TString detector, Int_t year,
452                                          Int_t reportNumber,
453                                          Int_t reportVersion) {
454   // Queries AliEn for existing reports matching the specified conditions
455   TString lsArg = fgkBaseFolder;
456   
457   TString detectorFolder = "";
458   if (detector.Length() > 0) {
459     detector.ToUpper();
460     // Check if <detector> is valid
461     if (!IsValidDetector(detector)) {
462       AliError(Form("Detector '%s' is not a valid detector/structure!",
463                     detector.Data()));
464       return 0;
465     }
466     // Some "detectors" don't have a folder of their own
467     detectorFolder = "/" + RealFolderName(detector);
468   } else detectorFolder = "/*";
469
470   lsArg += detectorFolder + "/RawSurvey";
471
472   TString yearFolder = "";
473   if (year > 1950) yearFolder.Form("/%d", year);
474   else yearFolder = "/*";
475
476   TString reportFolder = "";
477   if (reportNumber > 0) reportFolder.Form("/%d", reportNumber);
478   else reportFolder = "/*";
479
480   TString versionFolder = "";
481   if (reportVersion > 0) versionFolder.Form("_v%d", reportVersion);
482   else versionFolder = "_v*";
483
484   lsArg += yearFolder + reportFolder + versionFolder + ".txt";
485
486   Printf("");
487   Printf(Form("Looking for:  %s \n", lsArg.Data()));
488   
489   // Check if fGridUser is set and Connect to AliEn
490   if (0 == fGridUser.Length()) {
491     AliError("To use this method it's necessary to call SetGridUser(...) in advance.");
492     return 0;
493   } else if (!Connect(fgkStorage.Data(), fGridUser.Data())) {
494     AliError(Form("Error connecting to GRID"));
495     return 0;
496   }
497   return gGrid->Ls(lsArg);
498 }
499
500
501 //_____________________________________________________________________________
502 Int_t AliSurveyObj::ListReports(TString detector, Int_t year, 
503                                 Int_t reportNumber,
504                                 Int_t reportVersion) {
505   // Lists all available reports matching the specified conditions
506   // Returns the number of reports found
507
508   TGridResult *res = QueryReports(detector, year, reportNumber, reportVersion);
509   
510   if (0 == res) {
511     AliError("Query failed.");
512     return 0;
513   }
514
515   TString fn = "";
516   Int_t numberEntries = res->GetEntries();
517
518   if (numberEntries > 0) {
519     Printf("");
520     Printf(Form("%d reports found:", numberEntries));
521     for (int i = 0; i < res->GetEntries(); ++i) {
522       fn = res->GetFileNamePath(i);
523       Printf(Form("Detector:%s\tYear:%d\tEDMS Report Number:%d\tVersion:%d",
524                   FileNamePathToDetector(fn).Data(),
525                   FileNamePathToReportYear(fn),
526                   FileNamePathToReportNumber(fn),
527                   FileNamePathToReportVersion(fn)));
528     }
529     delete res;
530     return numberEntries;
531   } else {
532     AliInfo("No results found for the requested query.");
533     delete res;
534     return 0;
535   }
536 }
537
538
539 //_____________________________________________________________________________
540 void AliSurveyObj::SetGridUser(TString username){
541   // Set the username used to connect to the GRID
542   fGridUser = username;
543   return;
544 }
545
546
547 //_____________________________________________________________________________
548 TString &AliSurveyObj::Sanitize(TString str) {
549   // Cleans up a line of new line and carriage return characters.
550   // (Specially usefull for files created in Windows.)
551
552   str.Remove(TString::kTrailing, '\r');
553   str.Remove(TString::kTrailing, '\n');
554   str.Remove(TString::kTrailing, '\r');
555   if (!str.IsAscii()) {
556     AliWarning("Warning: Non-ASCII characters!\n");
557     str = "";
558   }
559   return str.Remove(TString::kBoth, ' ');
560 }
561
562
563 //_____________________________________________________________________________
564 Bool_t AliSurveyObj::ParseBuffer(const Char_t* buf) {
565   // Parses a character buffer assuming the format defined with the TS/SU
566   // http://aliceinfo/Offline/Activities/Alignment/SurveyInformation.html
567
568   // If the object is already filled clean it up
569   if (fIsValid) Reset();
570
571   // Copy the buffer to a TString to use Tokenize
572   TString buffer = TString(buf);
573   TObjArray *lines = buffer.Tokenize('\n');
574   TObjArray *dataLine = NULL; // Used to Tokenize each point/line read
575   TObjArray *colLine = NULL; // Used to Tokenize the column names
576
577   // Some local variables declarations and initializations
578   const Int_t kFieldCheck = 10;
579   Bool_t check[kFieldCheck];
580   TString tmp_name = "";
581   Float_t tmp_x = 0.0, tmp_y = 0.0, tmp_z = 0.0;
582   Float_t tmp_precX = 0.0, tmp_precY = 0.0, tmp_precZ = 0.0;
583   Char_t tmp_type = '\0';
584   Bool_t tmp_targ = kTRUE;
585   AliSurveyPoint *dp = 0;
586   for (Int_t i = 0; i < kFieldCheck; ++i) check[i] = kFALSE;
587
588   Int_t nrLines = lines->GetEntries();
589   Printf("Lines in file: %d\n", nrLines); 
590
591   // The main cycle, the buffer is parsed a line at a time
592   TString currLine = "", nextLine = "";
593   for (Int_t i = 0; i < nrLines; ++i) {
594
595     // Get the next line
596     currLine = ((TObjString *)(lines->At(i)))->GetString().Data();
597     nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : "");
598     currLine = Sanitize(currLine);
599     nextLine = Sanitize(nextLine);
600     // Printf("\n%d: \"\"%s\"\"\"\n", i + 1, currLine.Data());
601     
602     // Skip empty line
603     if (0 == currLine.Length()) Printf("Info: Empty line skipped\n\n");
604
605     // The line contains a keyword
606     else if (currLine.BeginsWith(">") && !nextLine.BeginsWith(">")) {
607       currLine.Remove(TString::kLeading, '>');
608       currLine.Remove(TString::kTrailing, ':');
609       currLine.Remove(TString::kBoth, ' ');
610       nextLine.Remove(TString::kBoth, ' ');
611       // Printf(" -> Field: \"%s\"\n", currLine.Data());
612       
613       if (currLine.BeginsWith("Title", TString::kIgnoreCase)) {
614         // Report Title
615         fTitle = nextLine;
616         ++i;
617       } else if (currLine.BeginsWith("Date", TString::kIgnoreCase)) {
618         // Report(measurement) Date
619         fDate = nextLine;
620         ++i;
621       } else if (currLine.BeginsWith("Subdetector", TString::kIgnoreCase)) {
622         // Subdetector or structure
623         fDetector = nextLine;
624         ++i;
625       } else if (currLine.BeginsWith("Report URL", TString::kIgnoreCase)) {
626         // Report URL in EDMS
627         if (nextLine.BeginsWith("http://edms.cern.ch/document/", TString::kIgnoreCase) ||
628             nextLine.BeginsWith("https://edms.cern.ch/document/", TString::kIgnoreCase)) {
629           fURL = nextLine;
630           nextLine.Remove(TString::kTrailing, '/');
631           nextLine = nextLine(nextLine.Last('/') + 1, nextLine.Length() - nextLine.Last('/') + 1);
632           
633           Int_t sscanf_tmp = 0;
634           if (1 != sscanf(nextLine.Data(), "%d", &sscanf_tmp)) {
635             AliError("Survey text file sintax error! (incorrectly formated Report URL)");
636             lines->Delete();
637             return kFALSE;
638           }
639           fReportNr = nextLine.Atoi();
640           //Printf(" $$ %d $$\n", fReportNr);
641           ++i;
642         } else { 
643           // URL incorrectly formated
644           AliError("Survey text file sintax error! (incorrectly formated Report URL)");
645           return kFALSE;
646         }
647       } else if (currLine.BeginsWith("Version", TString::kIgnoreCase)) {
648         // Report version
649         if (!nextLine.IsDigit()) {
650           lines->Delete();
651           AliError("Survey text file sintax error! (incorrectly formated Report Version)");
652           return kFALSE;
653         }
654         fVersion = nextLine.Atoi();
655         ++i;
656       } else if (currLine.BeginsWith("General Observations", TString::kIgnoreCase)) {
657         // Observations
658         fObs = "";
659         // Can be more than 1 line. Loop until another keyword is found
660         while (('>' != nextLine[0]) && (nextLine.Length() > 0) && (i < nrLines)) {      
661           fObs += (0 == fObs.Length()) ? nextLine : " / " + nextLine;
662           ++i;
663           nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : "");
664           nextLine = Sanitize(nextLine);
665         }
666       } else if (currLine.BeginsWith("Coordinate System", TString::kIgnoreCase)) {
667         // Coordinate System
668         fCoordSys = nextLine;
669         ++i;
670       } else if (currLine.BeginsWith("Units", TString::kIgnoreCase)) {
671         // Measurement Unit
672         fUnits = nextLine;
673         ++i;
674       } else if (currLine.BeginsWith("Nr Columns", TString::kIgnoreCase)) {
675         // Number of columns in the "Data" section
676         if (!nextLine.IsDigit()) {
677           lines->Delete();
678           AliError("Survey text file sintax error! (incorrectly formated Number of Columns)");
679           return kFALSE;
680         }
681         fNrColumns = nextLine.Atoi();
682         ++i;
683       } else if (currLine.BeginsWith("Column Names", TString::kIgnoreCase)) {
684         // Column names separated by commas
685         fColNames = nextLine;
686         colLine = nextLine.Tokenize(',');
687         if (colLine->GetEntries() != fNrColumns) {
688           AliError("Survey text file sintax error! (Declared number of Columns doesn't match number of column names)");
689           colLine->Delete();
690           lines->Delete();
691           return kFALSE;
692         }
693         ++i;
694       } else if (currLine.BeginsWith("Data", TString::kIgnoreCase)) {
695         // Data section!
696         while ((nextLine.Length() > 0) && ('>' != nextLine[0])) {
697
698           // Printf("Data LINE: \"%s\": %d\n", nextLine.Data(), nextLine.Length());
699
700           // What is the separator used between fields?
701           // The allowed are: comma (','), tab ('\t'), and space (' ')
702           if (fNrColumns == nextLine.CountChar(',') + 1) dataLine = nextLine.Tokenize(',');
703           else if (fNrColumns == nextLine.CountChar('\t') + 1) dataLine = nextLine.Tokenize('\t');
704           else if (fNrColumns == nextLine.CountChar(' ') + 1) dataLine = nextLine.Tokenize(' ');
705           else {
706             // Error (No separator was found!)
707             AliError("Survey text file syntax error! Error processing data line!");
708             lines->Delete();
709             return kFALSE;
710           }
711           
712           if (dataLine->GetEntries() != fNrColumns) {
713             // The number of columns doesn't match the number specified in the header
714             AliError("Survey text file sintax error! (Number of entries in line is different from declared Number of Columns)");
715             dataLine->Delete();
716             lines->Delete();
717             return kFALSE;
718           }
719
720           // Reset the bits used to check if all the required fields are present
721           for (Int_t t = 0; t < kFieldCheck; ++t) check[t] = 0;
722
723           // Process the data line using the column names as index
724           for (Int_t j = 0; j < dataLine->GetEntries(); ++j) {
725             TString cn = ((TObjString *)(colLine->At(j)))->GetString();
726             TString value = ((TObjString *)(dataLine->At(j)))->GetString();
727             if (cn.BeginsWith("Point Name", TString::kIgnoreCase)) {
728               tmp_name = value;
729               check[0] = kTRUE;
730             } else if (cn.BeginsWith("X", TString::kIgnoreCase)) {
731               tmp_x = value.Atof();
732               check[1] = kTRUE;
733             } else if (cn.BeginsWith("Y", TString::kIgnoreCase)) {
734               tmp_y = value.Atof();
735               check[2] = kTRUE;
736             } else if (cn.BeginsWith("Z", TString::kIgnoreCase)) {
737               tmp_z = value.Atof();
738               check[3] = kTRUE;
739             } else if (cn.BeginsWith("Precision", TString::kIgnoreCase)) {
740               TString tmpCN = cn(0, cn.First('('));
741               Int_t precLength = TString("Precision").Length();
742               //Printf(" ====== %d ======= %d ====== \n", precLength, tmpCN.Length());
743               //Printf(" ====== %s ======= \n", tmpCN.Data());
744               if (precLength == tmpCN.Length()) {
745                 tmp_precX = tmp_precY = tmp_precZ = value.Atof();
746                 check[6] = kTRUE;
747               } else {
748                 TString axis = cn(precLength, tmpCN.Length() - precLength);
749                 if (axis.Contains('X', TString::kIgnoreCase)) {
750                   tmp_precX = value.Atof();
751                   check[7] = kTRUE;
752                 } else if (axis.Contains('Y', TString::kIgnoreCase)) {
753                   tmp_precY = value.Atof();
754                   check[8] = kTRUE;
755                 } else if (axis.Contains('Z', TString::kIgnoreCase)) {
756                   tmp_precZ = value.Atof();
757                   check[9] = kTRUE;
758                 } else {
759                   AliError("Survey text file sintax error! (Precision column name invalid)");
760                   dataLine->Delete();
761                   lines->Delete();
762                   return kFALSE;
763                 }
764               }
765             } else if (cn.BeginsWith("Point Type", TString::kIgnoreCase)) {
766               tmp_type = value.Data()[0];
767               check[4] = kTRUE;
768             } else if (cn.BeginsWith("Target Used", TString::kIgnoreCase)) {
769               tmp_targ = (value.Data()[0] == 'Y') ? kTRUE : kFALSE;
770               check[5] = kTRUE;
771             }
772
773             //Printf("--> %s\n", ((TObjString *)(dataLine->At(j)))->GetString().Data());
774           }
775
776           // Check if all the mandatory fields exist
777           Bool_t res = kTRUE, precInd = kTRUE;
778
779           // Target
780           if (kFALSE == check[5]) {
781             tmp_targ = kTRUE;
782             check[5] = kTRUE;
783           }
784           
785           // Individual axis precisions
786           for (Int_t t = 7; t < 10; ++t) precInd &= check[t];
787           if ((kFALSE == check[6]) && (kTRUE == precInd)) check[6] = kTRUE;
788
789           for (Int_t t = 0; t < kFieldCheck - 3; ++t) {
790             //Printf("RES(%d): %d\n", t, check[t]);
791             res &= check[t];
792           }
793           if (kTRUE == res) {
794             dp = new AliSurveyPoint(tmp_name, tmp_x, tmp_y, tmp_z, tmp_precX, tmp_precY, tmp_precZ, tmp_type, tmp_targ);
795             dp->PrintPoint();
796             AddPoint(dp);
797           } else {
798             AliError("Parsing error processing data line!");
799             dataLine->Delete();
800             lines->Delete();
801             return kFALSE;
802           }
803           
804           dataLine->Delete();
805           dataLine = NULL;
806           ++i;
807           nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : "");
808           nextLine = Sanitize(nextLine);
809         }
810       }
811     } else {
812       AliError("Survey text file sintax error!");
813       lines->Delete();
814       return kFALSE;
815     }
816   }
817   lines->Delete();
818   fIsValid = kTRUE;
819   return kTRUE;
820 }
821
822 //_____________________________________________________________________________
823 void AliSurveyObj::Reset() {
824   // Resets the AliSurveyObj to a clean object.
825   // Used if the same object is filled more than once
826   
827   if (fDataPoints) {
828     fDataPoints->Delete();
829     fDataPoints = 0;
830   }
831   fTitle = "";
832   fDate = "";
833   fDetector = "";
834   fURL = "http://edms.cern.ch/";
835   fReportNr = -1;
836   fVersion = -1;
837   fObs = "";
838   fCoordSys = "";
839   fUnits = "";
840   fNrColumns = -1;
841   fColNames = "";
842   fIsValid = kFALSE;
843   fDataPoints = new TObjArray(1);
844   fDataPoints->SetOwner(kTRUE);
845   return;
846 }
847