]>
Commit | Line | Data |
---|---|---|
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 | 36 | ClassImp(AliSurveyObj) |
75cab1ea | 37 | |
38 | ||
39 | const TString AliSurveyObj::fgkStorage = "alien://alice.cern.ch"; | |
40 | const TString AliSurveyObj::fgkBaseFolder = "/alice/data/Reference"; | |
41 | const TString AliSurveyObj::fgkValidDetectors = "ACORDE,BABYFRAME,BACKFRAME,\ | |
42 | EMCAL,FMD,HMPID,ITS,L3 MAGNET,MUON,MUON ABSORBERS,MUON DIPOLE,PHOS,PMD,\ | |
d2404e52 | 43 | SPACEFRAME,SUPERSTRUCTURE,T0,TOF,TPC,TRD,VZERO,ZDC,GRP"; |
75cab1ea | 44 | const TString AliSurveyObj::fgkGRPDetectors = "BABYFRAME,BACKFRAME,L3 MAGNET,\ |
45 | SPACEFRAME,MUON DIPOLE,MUON ABSORBERS,GRP"; | |
46 | const TString AliSurveyObj::fgkMUONDetectors = "MUON,SUPERSTRUCTURE"; | |
47 | ||
324b1730 | 48 | |
49 | //_____________________________________________________________________________ | |
50 | AliSurveyObj::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 | //_____________________________________________________________________________ | |
73 | AliSurveyObj::~AliSurveyObj() { | |
74 | //destructor | |
adfef030 | 75 | if (fDataPoints) { |
adfef030 | 76 | fDataPoints->Delete(); |
77 | fDataPoints = 0; | |
78 | } | |
324b1730 | 79 | } |
80 | ||
81 | ||
82 | //_____________________________________________________________________________ | |
83 | AliSurveyObj::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 | //_____________________________________________________________________________ |
110 | AliSurveyObj& 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 | //_____________________________________________________________________________ | |
138 | void 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 | //_____________________________________________________________________________ | |
146 | Bool_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 | //_____________________________________________________________________________ |
172 | Bool_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 | 210 | Bool_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 | //_____________________________________________________________________________ | |
220 | Bool_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 | //_____________________________________________________________________________ | |
235 | TString 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 | //_____________________________________________________________________________ | |
254 | Bool_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 | //_____________________________________________________________________________ | |
263 | Bool_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 | 331 | TString 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 | //_____________________________________________________________________________ |
349 | Int_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 | //_____________________________________________________________________________ | |
367 | Int_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 | //_____________________________________________________________________________ | |
389 | Int_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 | //_____________________________________________________________________________ | |
411 | void 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 | //_____________________________________________________________________________ | |
438 | TGridResult * 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 | //_____________________________________________________________________________ | |
488 | Int_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 | //_____________________________________________________________________________ | |
525 | void AliSurveyObj::SetGridUser(TString username){ | |
526 | // Set the username used to connect to the GRID | |
527 | fGridUser = username; | |
528 | return; | |
324b1730 | 529 | } |
530 | ||
531 | ||
532 | //_____________________________________________________________________________ | |
533 | TString &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 | //_____________________________________________________________________________ | |
550 | Bool_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 | 877 | void 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 |