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