]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliSurveyObj.cxx
Base class for mag. field map moved to STEERBase.
[u/mrichter/AliRoot.git] / 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
26#include "TROOT.h"
27#include "Riostream.h"
28#include "TObjArray.h"
29#include "TGrid.h"
75cab1ea 30#include "TGridResult.h"
324b1730 31#include "TFile.h"
32#include "TObjString.h"
33
34//AliROOT includes
35#include "AliLog.h"
36
324b1730 37ClassImp(AliSurveyObj)
75cab1ea 38
39
40const TString AliSurveyObj::fgkStorage = "alien://alice.cern.ch";
41const TString AliSurveyObj::fgkBaseFolder = "/alice/data/Reference";
42const TString AliSurveyObj::fgkValidDetectors = "ACORDE,BABYFRAME,BACKFRAME,\
43EMCAL,FMD,HMPID,ITS,L3 MAGNET,MUON,MUON ABSORBERS,MUON DIPOLE,PHOS,PMD,\
44SPACEFRAME,SUPERSTRUCTURE,T0,TOF,TPC,TRD,V0,ZDC,GRP";
45const TString AliSurveyObj::fgkGRPDetectors = "BABYFRAME,BACKFRAME,L3 MAGNET,\
46SPACEFRAME,MUON DIPOLE,MUON ABSORBERS,GRP";
47const TString AliSurveyObj::fgkMUONDetectors = "MUON,SUPERSTRUCTURE";
48
324b1730 49
50//_____________________________________________________________________________
51AliSurveyObj::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),
737100a1 65 fGridUser(""),
324b1730 66 fDataPoints(new TObjArray(1))
67{
68 // constructor
69 fDataPoints->SetOwner(kTRUE);
70}
71
72
73//_____________________________________________________________________________
74AliSurveyObj::~AliSurveyObj() {
75 //destructor
adfef030 76 if (fDataPoints) {
adfef030 77 fDataPoints->Delete();
78 fDataPoints = 0;
79 }
324b1730 80}
81
82
83//_____________________________________________________________________________
84AliSurveyObj::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),
737100a1 98 fGridUser(surveyObj.fGridUser),
324b1730 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
75cab1ea 109
324b1730 110//_____________________________________________________________________________
111AliSurveyObj& 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;
737100a1 127 fGridUser = surveyObj.fGridUser;
324b1730 128 TObject *curr = surveyObj.fDataPoints->First();
129 while (curr != 0) {
130 fDataPoints->Add(curr);
131 curr = surveyObj.fDataPoints->After(curr);
132 }
133 }
324b1730 134 return *this;
135}
136
137
138//_____________________________________________________________________________
139void AliSurveyObj::AddPoint(AliSurveyPoint* point) {
737100a1 140 // Adds a point to the TObjArray which containst the list of points
324b1730 141 fDataPoints->Add(point);
142 return;
143}
144
145
146//_____________________________________________________________________________
147Bool_t AliSurveyObj::Connect(const char *gridUrl, const char *user) {
737100a1 148 // Connects to the grid
324b1730 149
737100a1 150 // If the same "Grid" is alreay active, skip connection
adfef030 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 }
324b1730 163
adfef030 164 if(!gGrid) {
165 AliError("Connection failed!");
166 return kFALSE;
167 }
168 return kTRUE;
324b1730 169}
170
171
324b1730 172//_____________________________________________________________________________
173Bool_t AliSurveyObj::OpenFile(TString openString) {
737100a1 174 // Opens the file and reads it to a buffer
324b1730 175
75cab1ea 176 Printf("Open string: \n -> \"%s\"\n", openString.Data());
324b1730 177
737100a1 178 if (openString.BeginsWith("alien://"))
75cab1ea 179 if (!Connect(fgkStorage.Data(), fGridUser.Data())) {
737100a1 180 AliError(Form("Error connecting to GRID"));
181 return kFALSE;
182 }
324b1730 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
737100a1 192 char *buf = new Char_t[size + 1];
193 memset(buf, '\0', size + 1);
324b1730 194
195 file->Seek(0);
196 if ( file->ReadBuffer(buf, size) ) {
197 AliError("Error reading file contents to buffer!");
198 return kFALSE;
199 }
324b1730 200 Printf("%d bytes read!\n", file->GetBytesRead());
201
324b1730 202 ParseBuffer(buf);
203
204 file->Close();
205 delete[] buf;
206 return kTRUE;
207}
208
209
324b1730 210//_____________________________________________________________________________
75cab1ea 211Bool_t AliSurveyObj::FillFromLocalFile(const Char_t* filename) {
212 // Fills the object from a file in a local filesystem
737100a1 213
75cab1ea 214 TString fullOpenString = "file://" + TString(filename) + "?filetype=raw";
215
216 return OpenFile(fullOpenString);
217}
218
219
220//_____________________________________________________________________________
221Bool_t AliSurveyObj::IsValidDetector(TString detector) const {
222 // Checks if the detector name is valid
324b1730 223
adfef030 224 detector.ToUpper();
75cab1ea 225
226 TObjArray *dets = fgkValidDetectors.Tokenize(',');
227 TObject *found = dets->FindObject(detector);
adfef030 228 dets->Delete();
229 dets = 0;
230
75cab1ea 231 if (!found) return kFALSE;
232 else return kTRUE;
233}
234
235
236//_____________________________________________________________________________
237TString AliSurveyObj::RealFolderName(TString detector) const {
238 // Returns the actual folder name for a given detector
737100a1 239 // Some "detectors" don't have a folder of their own
75cab1ea 240
241 detector.ToUpper();
242 TString folderName = detector;
243
244 TObjArray *dets = fgkGRPDetectors.Tokenize(',');
245 if (dets->FindObject(detector)) folderName = "GRP";
adfef030 246 dets->Delete();
247 dets = 0;
248
75cab1ea 249 dets = fgkMUONDetectors.Tokenize(',');
250 if (dets->FindObject(detector)) folderName = "MUON";
251 dets->Delete();
252
253
254
adfef030 255 dets = 0;
256
75cab1ea 257 return folderName;
258}
259
260//_____________________________________________________________________________
261Bool_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//_____________________________________________________________________________
270Bool_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
737100a1 286 // Check if <year>, <reportNumber> and <reportVersion> are valid (roughly)
75cab1ea 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));
adfef030 308 return kFALSE;
309 }
324b1730 310
75cab1ea 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 /*
737100a1 328 // Finally composes the full string
75cab1ea 329 TString fullOpenString = "alien://" + fgkBaseFolder + "/" + detectorFolder + "/RawSurvey/";
adfef030 330 fullOpenString += Form("%d/%d_v%d.txt?filetype=raw", year, reportNumber, reportVersion);
75cab1ea 331 */
737100a1 332
324b1730 333 return OpenFile(fullOpenString);
334}
335
336
337//_____________________________________________________________________________
75cab1ea 338TString 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}
737100a1 352
75cab1ea 353///alice/cern.ch/user/r/rsilva/TRD/RawSurvey/2007/.816582_v2.txt/v1.0
324b1730 354
75cab1ea 355//_____________________________________________________________________________
356Int_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//_____________________________________________________________________________
374Int_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//_____________________________________________________________________________
396Int_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//_____________________________________________________________________________
418void 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//_____________________________________________________________________________
451TGridResult * 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//_____________________________________________________________________________
502Int_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//_____________________________________________________________________________
540void AliSurveyObj::SetGridUser(TString username){
541 // Set the username used to connect to the GRID
542 fGridUser = username;
543 return;
324b1730 544}
545
546
547//_____________________________________________________________________________
548TString &AliSurveyObj::Sanitize(TString str) {
737100a1 549 // Cleans up a line of new line and carriage return characters.
550 // (Specially usefull for files created in Windows.)
551
324b1730 552 str.Remove(TString::kTrailing, '\r');
553 str.Remove(TString::kTrailing, '\n');
573b6a5a 554 str.Remove(TString::kTrailing, '\r');
555 if (!str.IsAscii()) {
556 AliWarning("Warning: Non-ASCII characters!\n");
557 str = "";
558 }
324b1730 559 return str.Remove(TString::kBoth, ' ');
560}
561
562
563//_____________________________________________________________________________
564Bool_t AliSurveyObj::ParseBuffer(const Char_t* buf) {
737100a1 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
adfef030 569 if (fIsValid) Reset();
570
737100a1 571 // Copy the buffer to a TString to use Tokenize
324b1730 572 TString buffer = TString(buf);
573 TObjArray *lines = buffer.Tokenize('\n');
737100a1 574 TObjArray *dataLine = NULL; // Used to Tokenize each point/line read
324b1730 575 TObjArray *colLine = NULL; // Used to Tokenize the column names
576
737100a1 577 // Some local variables declarations and initializations
324b1730 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;
324b1730 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
737100a1 591 // The main cycle, the buffer is parsed a line at a time
324b1730 592 TString currLine = "", nextLine = "";
593 for (Int_t i = 0; i < nrLines; ++i) {
737100a1 594
595 // Get the next line
324b1730 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);
737100a1 600 // Printf("\n%d: \"\"%s\"\"\"\n", i + 1, currLine.Data());
324b1730 601
737100a1 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(">")) {
324b1730 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)) {
573b6a5a 629 fURL = nextLine;
324b1730 630 nextLine.Remove(TString::kTrailing, '/');
631 nextLine = nextLine(nextLine.Last('/') + 1, nextLine.Length() - nextLine.Last('/') + 1);
573b6a5a 632
573b6a5a 633 Int_t sscanf_tmp = 0;
573b6a5a 634 if (1 != sscanf(nextLine.Data(), "%d", &sscanf_tmp)) {
635 AliError("Survey text file sintax error! (incorrectly formated Report URL)");
324b1730 636 lines->Delete();
637 return kFALSE;
638 }
639 fReportNr = nextLine.Atoi();
573b6a5a 640 //Printf(" $$ %d $$\n", fReportNr);
324b1730 641 ++i;
737100a1 642 } else {
643 // URL incorrectly formated
324b1730 644 AliError("Survey text file sintax error! (incorrectly formated Report URL)");
645 return kFALSE;
646 }
647 } else if (currLine.BeginsWith("Version", TString::kIgnoreCase)) {
737100a1 648 // Report version
324b1730 649 if (!nextLine.IsDigit()) {
650 lines->Delete();
573b6a5a 651 AliError("Survey text file sintax error! (incorrectly formated Report Version)");
324b1730 652 return kFALSE;
653 }
654 fVersion = nextLine.Atoi();
655 ++i;
656 } else if (currLine.BeginsWith("General Observations", TString::kIgnoreCase)) {
737100a1 657 // Observations
324b1730 658 fObs = "";
737100a1 659 // Can be more than 1 line. Loop until another keyword is found
660 while (('>' != nextLine[0]) && (nextLine.Length() > 0) && (i < nrLines)) {
324b1730 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 }
324b1730 666 } else if (currLine.BeginsWith("Coordinate System", TString::kIgnoreCase)) {
737100a1 667 // Coordinate System
324b1730 668 fCoordSys = nextLine;
669 ++i;
670 } else if (currLine.BeginsWith("Units", TString::kIgnoreCase)) {
737100a1 671 // Measurement Unit
324b1730 672 fUnits = nextLine;
673 ++i;
674 } else if (currLine.BeginsWith("Nr Columns", TString::kIgnoreCase)) {
737100a1 675 // Number of columns in the "Data" section
324b1730 676 if (!nextLine.IsDigit()) {
677 lines->Delete();
573b6a5a 678 AliError("Survey text file sintax error! (incorrectly formated Number of Columns)");
324b1730 679 return kFALSE;
680 }
681 fNrColumns = nextLine.Atoi();
682 ++i;
683 } else if (currLine.BeginsWith("Column Names", TString::kIgnoreCase)) {
737100a1 684 // Column names separated by commas
324b1730 685 fColNames = nextLine;
686 colLine = nextLine.Tokenize(',');
687 if (colLine->GetEntries() != fNrColumns) {
573b6a5a 688 AliError("Survey text file sintax error! (Declared number of Columns doesn't match number of column names)");
324b1730 689 colLine->Delete();
690 lines->Delete();
691 return kFALSE;
692 }
693 ++i;
694 } else if (currLine.BeginsWith("Data", TString::kIgnoreCase)) {
737100a1 695 // Data section!
573b6a5a 696 while ((nextLine.Length() > 0) && ('>' != nextLine[0])) {
573b6a5a 697
737100a1 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 (' ')
adfef030 702 if (fNrColumns == nextLine.CountChar(',') + 1) dataLine = nextLine.Tokenize(',');
573b6a5a 703 else if (fNrColumns == nextLine.CountChar('\t') + 1) dataLine = nextLine.Tokenize('\t');
adfef030 704 else if (fNrColumns == nextLine.CountChar(' ') + 1) dataLine = nextLine.Tokenize(' ');
573b6a5a 705 else {
737100a1 706 // Error (No separator was found!)
573b6a5a 707 AliError("Survey text file syntax error! Error processing data line!");
708 lines->Delete();
709 return kFALSE;
710 }
737100a1 711
324b1730 712 if (dataLine->GetEntries() != fNrColumns) {
737100a1 713 // The number of columns doesn't match the number specified in the header
573b6a5a 714 AliError("Survey text file sintax error! (Number of entries in line is different from declared Number of Columns)");
324b1730 715 dataLine->Delete();
716 lines->Delete();
717 return kFALSE;
718 }
719
737100a1 720 // Reset the bits used to check if all the required fields are present
324b1730 721 for (Int_t t = 0; t < kFieldCheck; ++t) check[t] = 0;
722
737100a1 723 // Process the data line using the column names as index
324b1730 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
573b6a5a 773 //Printf("--> %s\n", ((TObjString *)(dataLine->At(j)))->GetString().Data());
324b1730 774 }
737100a1 775
776 // Check if all the mandatory fields exist
324b1730 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) {
573b6a5a 790 //Printf("RES(%d): %d\n", t, check[t]);
324b1730 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 }
573b6a5a 811 } else {
812 AliError("Survey text file sintax error!");
324b1730 813 lines->Delete();
814 return kFALSE;
815 }
816 }
817 lines->Delete();
818 fIsValid = kTRUE;
819 return kTRUE;
820}
821
adfef030 822//_____________________________________________________________________________
737100a1 823void AliSurveyObj::Reset() {
824 // Resets the AliSurveyObj to a clean object.
825 // Used if the same object is filled more than once
826
adfef030 827 if (fDataPoints) {
adfef030 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