]>
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) { | |
155 | AliInfo(Form("gGrid = %x; GridUrl = %s; gGrid->GridUrl() = %s", | |
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 | } | |
a3ba938d | 199 | AliInfo(Form("%d bytes read!\n", file->GetBytesRead())); |
324b1730 | 200 | |
324b1730 | 201 | ParseBuffer(buf); |
202 | ||
203 | file->Close(); | |
204 | delete[] buf; | |
205 | return kTRUE; | |
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); | |
adfef030 | 227 | dets->Delete(); |
228 | dets = 0; | |
229 | ||
75cab1ea | 230 | if (!found) return kFALSE; |
231 | else return kTRUE; | |
232 | } | |
233 | ||
234 | ||
235 | //_____________________________________________________________________________ | |
236 | TString AliSurveyObj::RealFolderName(TString detector) const { | |
237 | // Returns the actual folder name for a given detector | |
737100a1 | 238 | // Some "detectors" don't have a folder of their own |
75cab1ea | 239 | |
240 | detector.ToUpper(); | |
241 | TString folderName = detector; | |
242 | ||
243 | TObjArray *dets = fgkGRPDetectors.Tokenize(','); | |
244 | if (dets->FindObject(detector)) folderName = "GRP"; | |
adfef030 | 245 | dets->Delete(); |
246 | dets = 0; | |
247 | ||
75cab1ea | 248 | dets = fgkMUONDetectors.Tokenize(','); |
249 | if (dets->FindObject(detector)) folderName = "MUON"; | |
250 | dets->Delete(); | |
251 | ||
252 | ||
253 | ||
adfef030 | 254 | dets = 0; |
255 | ||
75cab1ea | 256 | return folderName; |
257 | } | |
258 | ||
259 | //_____________________________________________________________________________ | |
260 | Bool_t AliSurveyObj::Fill(TString detector, Int_t reportNumber, | |
261 | TString username) { | |
262 | // Fills the object from a file in the default storage location in AliEn. | |
263 | // The highest version available is selected. | |
264 | ||
265 | return Fill(detector, reportNumber, -1, username); | |
266 | } | |
267 | ||
268 | //_____________________________________________________________________________ | |
269 | Bool_t AliSurveyObj::Fill(TString detector, Int_t reportNumber, | |
270 | Int_t reportVersion, TString username) { | |
271 | // Fills the object from a file in the default storage location in AliEn. | |
272 | // A specific version is selected. | |
273 | ||
274 | detector.ToUpper(); | |
275 | ||
276 | // Check if <detector> is valid | |
277 | if (!IsValidDetector(detector)) { | |
278 | AliWarning(Form("Detector '%s' is not a valid detector/structure!", detector.Data())); | |
279 | return kFALSE; | |
280 | } | |
281 | ||
282 | // Some "detectors" don't have a folder of their own | |
283 | // TString detectorFolder = RealFolderName(detector); | |
284 | ||
737100a1 | 285 | // Check if <year>, <reportNumber> and <reportVersion> are valid (roughly) |
75cab1ea | 286 | if ((reportNumber < 1) || (reportVersion < -1) || (0 == reportVersion)) { |
287 | AliError("Invalid parameter values for AliSurveyObj::Fill. (Report Number or Report Version)"); | |
288 | return kFALSE; | |
289 | } | |
290 | ||
291 | // Check if the fGridUser is set, or specified | |
292 | if (username.Length() > 0) SetGridUser(username); | |
293 | else if (0 == fGridUser.Length()) { | |
294 | AliError("GRID username not specified and not previously set!"); | |
295 | return kFALSE; | |
296 | } | |
297 | ||
298 | // Query AliEn for the available reports | |
299 | TGridResult *res = QueryReports(detector, -1, reportNumber, reportVersion); | |
300 | if (!res) AliError(Form("Error querying AliEn for detector '%s', \ | |
301 | report number '%d' and report version '%d'.", | |
302 | detector.Data(), reportNumber, reportVersion)); | |
303 | Int_t numberEntries = res->GetEntries(); | |
304 | if (0 == numberEntries) { | |
305 | AliError(Form("No report found for detector '%s', report number '%d' and report version '%d'", | |
306 | detector.Data(), reportNumber, reportVersion)); | |
adfef030 | 307 | return kFALSE; |
308 | } | |
324b1730 | 309 | |
75cab1ea | 310 | TString fileNamePath = ""; |
311 | if (1 == numberEntries) fileNamePath = res->GetFileNamePath(0); | |
312 | else if (numberEntries > 1) { | |
313 | TString higherVerFNP = res->GetFileNamePath(0); | |
314 | Int_t lastYear = FileNamePathToReportYear(higherVerFNP); | |
315 | for (Int_t i = 1; i < numberEntries; ++i) { | |
316 | TString currFNP = res->GetFileNamePath(i); | |
317 | if (FileNamePathToReportVersion(currFNP) > | |
318 | FileNamePathToReportVersion(higherVerFNP)) higherVerFNP = currFNP; | |
319 | if (lastYear != FileNamePathToReportYear(currFNP)) | |
320 | 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."); | |
321 | } | |
322 | fileNamePath = higherVerFNP; | |
323 | } | |
324 | ||
325 | TString fullOpenString = "alien://" + fileNamePath + "?filetype=raw"; | |
326 | /* | |
737100a1 | 327 | // Finally composes the full string |
75cab1ea | 328 | TString fullOpenString = "alien://" + fgkBaseFolder + "/" + detectorFolder + "/RawSurvey/"; |
adfef030 | 329 | fullOpenString += Form("%d/%d_v%d.txt?filetype=raw", year, reportNumber, reportVersion); |
75cab1ea | 330 | */ |
737100a1 | 331 | |
324b1730 | 332 | return OpenFile(fullOpenString); |
333 | } | |
334 | ||
335 | ||
336 | //_____________________________________________________________________________ | |
75cab1ea | 337 | TString AliSurveyObj::FileNamePathToDetector(TString filename) const { |
338 | // Get the report number from the complete path in the format: | |
339 | // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt | |
340 | ||
341 | TString ret = ""; | |
342 | ||
343 | if (filename.Length() > fgkBaseFolder.Length()) { | |
344 | ret = filename.Remove(0, fgkBaseFolder.Length()); | |
345 | ret.Remove(TString::kLeading, '/'); | |
346 | ret = ret(0, ret.First('/')); | |
347 | if (!IsValidDetector(ret)) ret = ""; | |
348 | } | |
349 | return ret; | |
350 | } | |
737100a1 | 351 | |
75cab1ea | 352 | ///alice/cern.ch/user/r/rsilva/TRD/RawSurvey/2007/.816582_v2.txt/v1.0 |
324b1730 | 353 | |
75cab1ea | 354 | //_____________________________________________________________________________ |
355 | Int_t AliSurveyObj::FileNamePathToReportYear(TString filename) const { | |
356 | // Get the report year from the complete path in the format: | |
357 | // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt | |
358 | ||
359 | TString ret = ""; | |
360 | ||
361 | if (filename.Length() > fgkBaseFolder.Length()) { | |
362 | ret = filename.Remove(0, fgkBaseFolder.Length()); | |
363 | ret.Remove(TString::kLeading, '/'); | |
364 | Int_t beg = ret.First('/') + TString("RawSurvey/").Length() + 1; | |
365 | ret = ret(beg, ret.Last('/') - beg); | |
366 | return ret.Atoi(); | |
367 | } | |
368 | return -1; | |
369 | } | |
370 | ||
371 | ||
372 | //_____________________________________________________________________________ | |
373 | Int_t AliSurveyObj::FileNamePathToReportNumber(TString filename) const { | |
374 | // Get the report number from the complete path in the format: | |
375 | // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt | |
376 | ||
377 | TString ret = ""; | |
378 | ||
379 | if (filename.Length() > fgkBaseFolder.Length()) { | |
380 | ret = filename.Remove(0, fgkBaseFolder.Length()); | |
381 | ret.Remove(TString::kLeading, '/'); | |
382 | if ((ret.CountChar('/') > 3) || (ret.CountChar('.') > 1)) { | |
383 | AliWarning("Error getting the Report Number from the filename path!"); | |
384 | return -1; | |
385 | } | |
386 | ret = ret(ret.Last('/') + 1 , ret.Last('_') - ret.Last('/') - 1); | |
387 | return ret.Atoi(); | |
388 | } | |
389 | AliWarning("Error getting the Report Number from the filename path!"); | |
390 | return -1; | |
391 | } | |
392 | ||
393 | ||
394 | //_____________________________________________________________________________ | |
395 | Int_t AliSurveyObj::FileNamePathToReportVersion(TString filename) const { | |
396 | // Get the report version from the complete path in the format: | |
397 | // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt | |
398 | ||
399 | TString ret = ""; | |
400 | ||
401 | if (filename.Length() > fgkBaseFolder.Length()) { | |
402 | ret = filename.Remove(0, fgkBaseFolder.Length()); | |
403 | ret.Remove(TString::kLeading, '/'); | |
404 | if ((ret.CountChar('/') > 3) || (ret.CountChar('.') > 1)) { | |
405 | AliWarning("Error getting the Report Version from the filename path!"); | |
406 | return -1; | |
407 | } | |
408 | ret = ret(ret.Last('_') + 1 + 1 , ret.Last('.') - ret.Last('_') - 1 - 1); | |
409 | return ret.Atoi(); | |
410 | } | |
411 | AliWarning("Error getting the Report Version from the filename path!"); | |
412 | return -1; | |
413 | } | |
414 | ||
415 | ||
416 | //_____________________________________________________________________________ | |
417 | void AliSurveyObj::ListValidDetectors() { | |
a3ba938d | 418 | // List the valid detector names |
419 | Printf(""); | |
420 | Printf("Listing all valid detectors:\n"); | |
421 | TObjArray *dets = fgkValidDetectors.Tokenize(','); | |
422 | for (int i = 0; i < dets->GetEntries(); ++i) | |
423 | Printf("%s", ((TObjString *) dets->At(i))->GetString().Data()); | |
424 | dets->Delete(); | |
425 | dets = 0; | |
426 | Printf(""); | |
427 | Printf("Some reports are stored in more general folders.\n" | |
428 | "These reports can be opened using either name, the original or the\n" | |
429 | "folder name. Example: 'SPACEFRAME' or 'GRP' are both valid when\n" | |
430 | "opening a report for the Spaceframe.\n\n" | |
431 | "Detectors stored in 'MUON' folder:"); | |
432 | dets = fgkMUONDetectors.Tokenize(','); | |
433 | for (int i = 0; i < dets->GetEntries(); ++i) | |
434 | Printf("%s", ((TObjString *) dets->At(i))->GetString().Data()); | |
435 | dets->Delete(); | |
436 | dets = 0; | |
437 | Printf(""); | |
438 | Printf("Detectors stored in 'GRP' folder:"); | |
439 | dets = fgkGRPDetectors.Tokenize(','); | |
440 | for (int i = 0; i < dets->GetEntries(); ++i) | |
441 | Printf("%s", ((TObjString *) dets->At(i))->GetString().Data()); | |
442 | dets->Delete(); | |
443 | dets = 0; | |
444 | return; | |
75cab1ea | 445 | } |
446 | ||
447 | ||
448 | //_____________________________________________________________________________ | |
449 | TGridResult * AliSurveyObj::QueryReports(TString detector, Int_t year, | |
450 | Int_t reportNumber, | |
451 | Int_t reportVersion) { | |
452 | // Queries AliEn for existing reports matching the specified conditions | |
453 | TString lsArg = fgkBaseFolder; | |
454 | ||
455 | TString detectorFolder = ""; | |
456 | if (detector.Length() > 0) { | |
457 | detector.ToUpper(); | |
458 | // Check if <detector> is valid | |
459 | if (!IsValidDetector(detector)) { | |
460 | AliError(Form("Detector '%s' is not a valid detector/structure!", | |
461 | detector.Data())); | |
462 | return 0; | |
463 | } | |
464 | // Some "detectors" don't have a folder of their own | |
465 | detectorFolder = "/" + RealFolderName(detector); | |
466 | } else detectorFolder = "/*"; | |
467 | ||
468 | lsArg += detectorFolder + "/RawSurvey"; | |
469 | ||
470 | TString yearFolder = ""; | |
471 | if (year > 1950) yearFolder.Form("/%d", year); | |
472 | else yearFolder = "/*"; | |
473 | ||
474 | TString reportFolder = ""; | |
475 | if (reportNumber > 0) reportFolder.Form("/%d", reportNumber); | |
476 | else reportFolder = "/*"; | |
477 | ||
478 | TString versionFolder = ""; | |
479 | if (reportVersion > 0) versionFolder.Form("_v%d", reportVersion); | |
480 | else versionFolder = "_v*"; | |
481 | ||
482 | lsArg += yearFolder + reportFolder + versionFolder + ".txt"; | |
483 | ||
a3ba938d | 484 | AliInfo(Form("\nLooking for: %s \n", lsArg.Data())); |
75cab1ea | 485 | |
486 | // Check if fGridUser is set and Connect to AliEn | |
487 | if (0 == fGridUser.Length()) { | |
488 | AliError("To use this method it's necessary to call SetGridUser(...) in advance."); | |
489 | return 0; | |
490 | } else if (!Connect(fgkStorage.Data(), fGridUser.Data())) { | |
491 | AliError(Form("Error connecting to GRID")); | |
492 | return 0; | |
493 | } | |
494 | return gGrid->Ls(lsArg); | |
495 | } | |
496 | ||
497 | ||
498 | //_____________________________________________________________________________ | |
499 | Int_t AliSurveyObj::ListReports(TString detector, Int_t year, | |
500 | Int_t reportNumber, | |
501 | Int_t reportVersion) { | |
502 | // Lists all available reports matching the specified conditions | |
503 | // Returns the number of reports found | |
504 | ||
505 | TGridResult *res = QueryReports(detector, year, reportNumber, reportVersion); | |
506 | ||
507 | if (0 == res) { | |
508 | AliError("Query failed."); | |
509 | return 0; | |
510 | } | |
511 | ||
512 | TString fn = ""; | |
513 | Int_t numberEntries = res->GetEntries(); | |
514 | ||
515 | if (numberEntries > 0) { | |
516 | Printf(""); | |
517 | Printf(Form("%d reports found:", numberEntries)); | |
518 | for (int i = 0; i < res->GetEntries(); ++i) { | |
519 | fn = res->GetFileNamePath(i); | |
520 | Printf(Form("Detector:%s\tYear:%d\tEDMS Report Number:%d\tVersion:%d", | |
521 | FileNamePathToDetector(fn).Data(), | |
522 | FileNamePathToReportYear(fn), | |
523 | FileNamePathToReportNumber(fn), | |
524 | FileNamePathToReportVersion(fn))); | |
525 | } | |
526 | delete res; | |
527 | return numberEntries; | |
528 | } else { | |
529 | AliInfo("No results found for the requested query."); | |
530 | delete res; | |
531 | return 0; | |
532 | } | |
533 | } | |
534 | ||
535 | ||
536 | //_____________________________________________________________________________ | |
537 | void AliSurveyObj::SetGridUser(TString username){ | |
538 | // Set the username used to connect to the GRID | |
539 | fGridUser = username; | |
540 | return; | |
324b1730 | 541 | } |
542 | ||
543 | ||
544 | //_____________________________________________________________________________ | |
545 | TString &AliSurveyObj::Sanitize(TString str) { | |
737100a1 | 546 | // Cleans up a line of new line and carriage return characters. |
547 | // (Specially usefull for files created in Windows.) | |
548 | ||
324b1730 | 549 | str.Remove(TString::kTrailing, '\r'); |
550 | str.Remove(TString::kTrailing, '\n'); | |
573b6a5a | 551 | str.Remove(TString::kTrailing, '\r'); |
a3ba938d | 552 | |
573b6a5a | 553 | if (!str.IsAscii()) { |
554 | AliWarning("Warning: Non-ASCII characters!\n"); | |
555 | str = ""; | |
556 | } | |
324b1730 | 557 | return str.Remove(TString::kBoth, ' '); |
558 | } | |
559 | ||
560 | ||
561 | //_____________________________________________________________________________ | |
562 | Bool_t AliSurveyObj::ParseBuffer(const Char_t* buf) { | |
737100a1 | 563 | // Parses a character buffer assuming the format defined with the TS/SU |
564 | // http://aliceinfo/Offline/Activities/Alignment/SurveyInformation.html | |
565 | ||
566 | // If the object is already filled clean it up | |
adfef030 | 567 | if (fIsValid) Reset(); |
568 | ||
737100a1 | 569 | // Copy the buffer to a TString to use Tokenize |
324b1730 | 570 | TString buffer = TString(buf); |
a3ba938d | 571 | TObjArray *linesRaw = buffer.Tokenize('\n'); |
572 | // replace the array of lines with an array of sanitized lines | |
573 | // in the process we remove empty lines, particularly disturbing | |
574 | // in case of dos fileformat | |
575 | TString oneLine = ""; | |
576 | TObjString* oneLineObj = 0; | |
577 | TObjArray *lines = new TObjArray(); | |
578 | for(Int_t i=0; i<linesRaw->GetEntries(); i++) | |
579 | { | |
580 | oneLine = ((TObjString *)(linesRaw->At(i)))->GetString().Data(); | |
581 | oneLine = Sanitize(oneLine); | |
582 | if (oneLine.Length() == 0) continue; | |
583 | oneLineObj = new TObjString(oneLine); | |
584 | lines->Add(oneLineObj); | |
585 | } | |
586 | ||
587 | linesRaw->Delete(); | |
588 | delete linesRaw; | |
589 | linesRaw = NULL; | |
590 | ||
737100a1 | 591 | TObjArray *dataLine = NULL; // Used to Tokenize each point/line read |
324b1730 | 592 | TObjArray *colLine = NULL; // Used to Tokenize the column names |
593 | ||
737100a1 | 594 | // Some local variables declarations and initializations |
324b1730 | 595 | const Int_t kFieldCheck = 10; |
2f29b48b | 596 | Bool_t check[kFieldCheck]; // used to check that mandatory column names are not missing |
597 | for (Int_t i = 0; i < kFieldCheck; ++i) check[i] = kFALSE; | |
68e43693 | 598 | TString tmpname = ""; |
599 | Float_t tmpx = 0.0, tmpy = 0.0, tmpz = 0.0; | |
2f29b48b | 600 | Float_t tmpprecX = -1., tmpprecY = -1., tmpprecZ = -1.; |
68e43693 | 601 | Char_t tmptype = '\0'; |
602 | Bool_t tmptarg = kTRUE; | |
324b1730 | 603 | AliSurveyPoint *dp = 0; |
2f29b48b | 604 | TString *orderedValues[9] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; |
605 | TString value[9]; | |
324b1730 | 606 | |
607 | Int_t nrLines = lines->GetEntries(); | |
608 | Printf("Lines in file: %d\n", nrLines); | |
609 | ||
737100a1 | 610 | // The main cycle, the buffer is parsed a line at a time |
324b1730 | 611 | TString currLine = "", nextLine = ""; |
612 | for (Int_t i = 0; i < nrLines; ++i) { | |
737100a1 | 613 | |
614 | // Get the next line | |
324b1730 | 615 | currLine = ((TObjString *)(lines->At(i)))->GetString().Data(); |
616 | nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : ""); | |
a3ba938d | 617 | // Printf("%d: \"%s\"", i, currLine.Data()); |
618 | // Printf("%d: \"%s\"\n", i+1, nextLine.Data()); | |
324b1730 | 619 | |
737100a1 | 620 | // The line contains a keyword |
a3ba938d | 621 | if (currLine.BeginsWith(">") && !nextLine.BeginsWith(">")) { |
324b1730 | 622 | currLine.Remove(TString::kLeading, '>'); |
623 | currLine.Remove(TString::kTrailing, ':'); | |
624 | currLine.Remove(TString::kBoth, ' '); | |
625 | nextLine.Remove(TString::kBoth, ' '); | |
2f29b48b | 626 | AliDebug(2, Form(" -> field line: \"%s\"\n", currLine.Data())); |
627 | AliDebug(2, Form(" -> value line: \"%s\"\n", nextLine.Data())); | |
324b1730 | 628 | |
629 | if (currLine.BeginsWith("Title", TString::kIgnoreCase)) { | |
630 | // Report Title | |
631 | fTitle = nextLine; | |
632 | ++i; | |
633 | } else if (currLine.BeginsWith("Date", TString::kIgnoreCase)) { | |
634 | // Report(measurement) Date | |
635 | fDate = nextLine; | |
636 | ++i; | |
637 | } else if (currLine.BeginsWith("Subdetector", TString::kIgnoreCase)) { | |
638 | // Subdetector or structure | |
639 | fDetector = nextLine; | |
640 | ++i; | |
641 | } else if (currLine.BeginsWith("Report URL", TString::kIgnoreCase)) { | |
642 | // Report URL in EDMS | |
643 | if (nextLine.BeginsWith("http://edms.cern.ch/document/", TString::kIgnoreCase) || | |
644 | nextLine.BeginsWith("https://edms.cern.ch/document/", TString::kIgnoreCase)) { | |
573b6a5a | 645 | fURL = nextLine; |
324b1730 | 646 | nextLine.Remove(TString::kTrailing, '/'); |
647 | nextLine = nextLine(nextLine.Last('/') + 1, nextLine.Length() - nextLine.Last('/') + 1); | |
573b6a5a | 648 | |
68e43693 | 649 | Int_t sscanftmp = 0; |
650 | if (1 != sscanf(nextLine.Data(), "%d", &sscanftmp)) { | |
a3ba938d | 651 | AliError("Survey text file sintax error! (incorrectly formatted Report URL)"); |
324b1730 | 652 | lines->Delete(); |
a3ba938d | 653 | delete lines; lines = NULL; |
324b1730 | 654 | return kFALSE; |
655 | } | |
656 | fReportNr = nextLine.Atoi(); | |
573b6a5a | 657 | //Printf(" $$ %d $$\n", fReportNr); |
324b1730 | 658 | ++i; |
737100a1 | 659 | } else { |
a3ba938d | 660 | // URL incorrectly formatted |
661 | AliError("Survey text file sintax error! (incorrectly formatted Report URL)"); | |
324b1730 | 662 | return kFALSE; |
663 | } | |
664 | } else if (currLine.BeginsWith("Version", TString::kIgnoreCase)) { | |
737100a1 | 665 | // Report version |
324b1730 | 666 | if (!nextLine.IsDigit()) { |
667 | lines->Delete(); | |
a3ba938d | 668 | delete lines; lines = NULL; |
669 | AliError("Survey text file sintax error! (incorrectly formatted Report Version)"); | |
324b1730 | 670 | return kFALSE; |
671 | } | |
672 | fVersion = nextLine.Atoi(); | |
673 | ++i; | |
674 | } else if (currLine.BeginsWith("General Observations", TString::kIgnoreCase)) { | |
737100a1 | 675 | // Observations |
324b1730 | 676 | fObs = ""; |
737100a1 | 677 | // Can be more than 1 line. Loop until another keyword is found |
678 | while (('>' != nextLine[0]) && (nextLine.Length() > 0) && (i < nrLines)) { | |
324b1730 | 679 | fObs += (0 == fObs.Length()) ? nextLine : " / " + nextLine; |
680 | ++i; | |
681 | nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : ""); | |
324b1730 | 682 | } |
324b1730 | 683 | } else if (currLine.BeginsWith("Coordinate System", TString::kIgnoreCase)) { |
737100a1 | 684 | // Coordinate System |
324b1730 | 685 | fCoordSys = nextLine; |
686 | ++i; | |
687 | } else if (currLine.BeginsWith("Units", TString::kIgnoreCase)) { | |
737100a1 | 688 | // Measurement Unit |
324b1730 | 689 | fUnits = nextLine; |
690 | ++i; | |
691 | } else if (currLine.BeginsWith("Nr Columns", TString::kIgnoreCase)) { | |
737100a1 | 692 | // Number of columns in the "Data" section |
324b1730 | 693 | if (!nextLine.IsDigit()) { |
694 | lines->Delete(); | |
a3ba938d | 695 | delete lines; lines = NULL; |
696 | AliError("Survey text file sintax error! (incorrectly formatted Number of Columns)"); | |
324b1730 | 697 | return kFALSE; |
698 | } | |
699 | fNrColumns = nextLine.Atoi(); | |
700 | ++i; | |
701 | } else if (currLine.BeginsWith("Column Names", TString::kIgnoreCase)) { | |
737100a1 | 702 | // Column names separated by commas |
324b1730 | 703 | fColNames = nextLine; |
704 | colLine = nextLine.Tokenize(','); | |
705 | if (colLine->GetEntries() != fNrColumns) { | |
573b6a5a | 706 | AliError("Survey text file sintax error! (Declared number of Columns doesn't match number of column names)"); |
324b1730 | 707 | colLine->Delete(); |
708 | lines->Delete(); | |
a3ba938d | 709 | delete lines; lines = NULL; |
324b1730 | 710 | return kFALSE; |
711 | } | |
712 | ++i; | |
2f29b48b | 713 | |
714 | // booleans to track if precision for 1 axis is defined in more than one column | |
715 | Bool_t prX = kFALSE; | |
716 | Bool_t prY = kFALSE; | |
717 | Bool_t prZ = kFALSE; | |
718 | ||
719 | for (Int_t j = 0; j < fNrColumns; ++j) { | |
720 | TString cn = ((TObjString *)(colLine->At(j)))->GetString(); | |
721 | if (cn.BeginsWith("Point Name", TString::kIgnoreCase)) { | |
722 | orderedValues[0] = &value[j]; | |
723 | check[0] = kTRUE; | |
724 | } else if (cn.BeginsWith("X", TString::kIgnoreCase)) { | |
725 | orderedValues[1] = &value[j]; | |
726 | check[1] = kTRUE; | |
727 | } else if (cn.BeginsWith("Y", TString::kIgnoreCase)) { | |
728 | orderedValues[2] = &value[j]; | |
729 | check[2] = kTRUE; | |
730 | } else if (cn.BeginsWith("Z", TString::kIgnoreCase)) { | |
731 | orderedValues[3] = &value[j]; | |
732 | check[3] = kTRUE; | |
733 | } else if (cn.BeginsWith("Precision", TString::kIgnoreCase)) { | |
734 | TString tmpCN = cn(0, cn.First('(')); | |
735 | Int_t precLength = TString("Precision").Length(); | |
736 | if (precLength == tmpCN.Length()) { | |
737 | if(!orderedValues[6]){ | |
738 | orderedValues[6] = &value[j]; | |
739 | check[6] = kTRUE; | |
740 | }else{ | |
741 | AliWarning("Global precision will not be used for X axis"); | |
742 | } | |
743 | if(!orderedValues[7]){ | |
744 | orderedValues[7] = &value[j]; | |
745 | check[7] = kTRUE; | |
746 | }else{ | |
747 | AliWarning("Global precision will not be used for Y axis"); | |
748 | } | |
749 | if(!orderedValues[8]){ | |
750 | orderedValues[8] = &value[j]; | |
751 | check[8] = kTRUE; | |
752 | }else{ | |
753 | AliWarning("Global precision will not be used for Z axis"); | |
754 | } | |
755 | } else { | |
756 | Bool_t orXYZ = kFALSE; | |
757 | TString axis = cn(precLength, tmpCN.Length() - precLength); | |
758 | if (axis.Contains('X', TString::kIgnoreCase)) { | |
759 | if(!prX){ | |
760 | orderedValues[6] = &value[j]; | |
761 | check[6] = kTRUE; | |
762 | orXYZ = kTRUE; | |
763 | prX = kTRUE; | |
764 | }else{ | |
765 | AliError("Precision for X axis was already set!"); | |
766 | return kFALSE; | |
767 | } | |
768 | } | |
769 | if (axis.Contains('Y', TString::kIgnoreCase)) { | |
770 | if(!prY){ | |
771 | orderedValues[7] = &value[j]; | |
772 | check[7] = kTRUE; | |
773 | orXYZ = kTRUE; | |
774 | prY = kTRUE; | |
775 | }else{ | |
776 | AliError("Precision for Y axis was already set!"); | |
777 | return kFALSE; | |
778 | } | |
779 | } | |
780 | if (axis.Contains('Z', TString::kIgnoreCase)) { | |
781 | if(!prZ){ | |
782 | orderedValues[8] = &value[j]; | |
783 | check[8] = kTRUE; | |
784 | orXYZ = kTRUE; | |
785 | prZ = kTRUE; | |
786 | }else{ | |
787 | AliError("Precision for Z axis was already set!"); | |
788 | return kFALSE; | |
789 | } | |
790 | } | |
791 | if(!orXYZ) | |
792 | { | |
793 | AliError("Survey text file sintax error: precision column name does not refer to any axis!"); | |
794 | return kFALSE; | |
795 | } | |
796 | } | |
797 | } else if (cn.BeginsWith("Point Type", TString::kIgnoreCase)) { | |
798 | orderedValues[4] = &value[j]; | |
799 | check[4] = kTRUE; | |
800 | } else if (cn.BeginsWith("Target Used", TString::kIgnoreCase)) { | |
801 | orderedValues[5] = &value[j]; | |
802 | check[5] = kTRUE; | |
803 | } | |
804 | } | |
805 | ||
806 | // Check if all the mandatory fields exist in the line with column names | |
807 | if(!check[0]){ | |
a3ba938d | 808 | AliError("Missing mandatory column \"Point Name\"!"); |
2f29b48b | 809 | return kFALSE; |
810 | } | |
811 | if(!(check[1]&&check[2]&&check[3])){ | |
a3ba938d | 812 | AliError("Missing one or more mandatory columns for coordinates \"X\",\"Y\",\"Z\""); |
2f29b48b | 813 | return kFALSE; |
814 | } | |
815 | if(!check[4]){ | |
a3ba938d | 816 | AliError("Missing mandatory column \"Point Type\"!"); |
2f29b48b | 817 | return kFALSE; |
818 | } | |
819 | if(!(check[6]&&check[7]&&check[8])){ | |
a3ba938d | 820 | AliError("Missing one or more mandatory columns for precision along \"X\",\"Y\",\"Z\" axes"); |
2f29b48b | 821 | return kFALSE; |
822 | } | |
823 | ||
324b1730 | 824 | } else if (currLine.BeginsWith("Data", TString::kIgnoreCase)) { |
737100a1 | 825 | // Data section! |
573b6a5a | 826 | while ((nextLine.Length() > 0) && ('>' != nextLine[0])) { |
573b6a5a | 827 | |
737100a1 | 828 | // Printf("Data LINE: \"%s\": %d\n", nextLine.Data(), nextLine.Length()); |
829 | ||
830 | // What is the separator used between fields? | |
831 | // The allowed are: comma (','), tab ('\t'), and space (' ') | |
2f29b48b | 832 | if (fNrColumns == nextLine.CountChar(',') + 1) dataLine = nextLine.Tokenize(','); |
833 | else if (fNrColumns == nextLine.CountChar('\t') + 1) dataLine = nextLine.Tokenize('\t'); | |
834 | else if (fNrColumns == nextLine.CountChar(' ') + 1) dataLine = nextLine.Tokenize(' '); | |
835 | else { | |
836 | // Error (No separator was found!) | |
837 | AliError("Survey text file syntax error! Error processing data line!"); | |
838 | lines->Delete(); | |
a3ba938d | 839 | delete lines; lines = NULL; |
2f29b48b | 840 | return kFALSE; |
841 | } | |
842 | ||
324b1730 | 843 | if (dataLine->GetEntries() != fNrColumns) { |
737100a1 | 844 | // The number of columns doesn't match the number specified in the header |
2f29b48b | 845 | AliError("Survey text file sintax error! (Number of entries in line is different from number of Columns)"); |
324b1730 | 846 | dataLine->Delete(); |
847 | lines->Delete(); | |
a3ba938d | 848 | delete lines; lines = NULL; |
324b1730 | 849 | return kFALSE; |
850 | } | |
851 | ||
737100a1 | 852 | // Process the data line using the column names as index |
324b1730 | 853 | for (Int_t j = 0; j < dataLine->GetEntries(); ++j) { |
2f29b48b | 854 | value[j] = ((TObjString *)(dataLine->At(j)))->GetString(); |
324b1730 | 855 | } |
2f29b48b | 856 | tmpname = *orderedValues[0]; |
857 | tmpx = orderedValues[1]->Atof(); | |
858 | tmpy = orderedValues[2]->Atof(); | |
859 | tmpz = orderedValues[3]->Atof(); | |
860 | tmpprecX = orderedValues[6]->Atof(); | |
861 | tmpprecY = orderedValues[7]->Atof(); | |
862 | tmpprecZ = orderedValues[8]->Atof(); | |
863 | tmptype = orderedValues[4]->Data()[0]; | |
864 | if(orderedValues[5]) tmptarg = (orderedValues[5]->Data()[0] == 'Y') ? kTRUE : kFALSE; | |
865 | ||
866 | dp = new AliSurveyPoint(tmpname, tmpx, tmpy, tmpz, tmpprecX, tmpprecY, tmpprecZ, tmptype, tmptarg); | |
a3ba938d | 867 | if(AliLog::GetDebugLevel("","AliSurveyObj")>1) dp->PrintPoint(); |
2f29b48b | 868 | AddPoint(dp); |
324b1730 | 869 | |
324b1730 | 870 | dataLine->Delete(); |
871 | dataLine = NULL; | |
872 | ++i; | |
873 | nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : ""); | |
324b1730 | 874 | } |
875 | } | |
573b6a5a | 876 | } else { |
877 | AliError("Survey text file sintax error!"); | |
324b1730 | 878 | lines->Delete(); |
a3ba938d | 879 | delete lines; lines = NULL; |
324b1730 | 880 | return kFALSE; |
881 | } | |
882 | } | |
883 | lines->Delete(); | |
a3ba938d | 884 | delete lines; lines = NULL; |
324b1730 | 885 | fIsValid = kTRUE; |
886 | return kTRUE; | |
887 | } | |
888 | ||
adfef030 | 889 | //_____________________________________________________________________________ |
737100a1 | 890 | void AliSurveyObj::Reset() { |
891 | // Resets the AliSurveyObj to a clean object. | |
892 | // Used if the same object is filled more than once | |
893 | ||
adfef030 | 894 | if (fDataPoints) { |
adfef030 | 895 | fDataPoints->Delete(); |
896 | fDataPoints = 0; | |
897 | } | |
898 | fTitle = ""; | |
899 | fDate = ""; | |
900 | fDetector = ""; | |
901 | fURL = "http://edms.cern.ch/"; | |
902 | fReportNr = -1; | |
903 | fVersion = -1; | |
904 | fObs = ""; | |
905 | fCoordSys = ""; | |
906 | fUnits = ""; | |
907 | fNrColumns = -1; | |
908 | fColNames = ""; | |
909 | fIsValid = kFALSE; | |
910 | fDataPoints = new TObjArray(1); | |
911 | fDataPoints->SetOwner(kTRUE); | |
912 | return; | |
913 | } | |
914 |