1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
16 /////////////////////////////////////////////////////////////////////
18 // class AliSurveyObj //
19 // Retrieve and Convert survey data into ROOT Objects //
21 /////////////////////////////////////////////////////////////////////
23 #include "AliSurveyObj.h"
27 #include "Riostream.h"
28 #include "TObjArray.h"
31 #include "TObjString.h"
36 ClassImp(AliSurveyObj)
38 //_____________________________________________________________________________
39 AliSurveyObj::AliSurveyObj():
44 fURL("http://edms.cern.ch/"),
54 fDataPoints(new TObjArray(1))
57 fDataPoints->SetOwner(kTRUE);
61 //_____________________________________________________________________________
62 AliSurveyObj::~AliSurveyObj() {
65 for (Int_t i = 0; i < fDataPoints->GetEntries(); ++i) delete fDataPoints->At(i);
66 fDataPoints->Delete();
72 //_____________________________________________________________________________
73 AliSurveyObj::AliSurveyObj(const AliSurveyObj& surveyObj):
75 fTitle(surveyObj.fTitle),
76 fDate(surveyObj.fDate),
77 fDetector(surveyObj.fDetector),
79 fReportNr(surveyObj.fReportNr),
80 fVersion(surveyObj.fVersion),
82 fCoordSys(surveyObj.fCoordSys),
83 fUnits(surveyObj.fUnits),
84 fNrColumns(surveyObj.fNrColumns),
85 fColNames(surveyObj.fColNames),
86 fIsValid(surveyObj.fIsValid),
87 fGridUser(surveyObj.fGridUser),
88 fDataPoints(new TObjArray(1))
91 TObject *curr = surveyObj.fDataPoints->First();
93 fDataPoints->Add(curr);
94 curr = surveyObj.fDataPoints->After(curr);
98 //_____________________________________________________________________________
99 AliSurveyObj& AliSurveyObj::operator=(const AliSurveyObj& surveyObj)
101 // assignment operator
102 if (this != &surveyObj) {
103 fTitle = surveyObj.fTitle;
104 fDate = surveyObj.fDate;
105 fDetector = surveyObj.fDetector;
106 fURL = surveyObj.fURL;
107 fReportNr = surveyObj.fReportNr;
108 fVersion = surveyObj.fVersion;
109 fObs = surveyObj.fObs;
110 fCoordSys = surveyObj.fCoordSys;
111 fUnits = surveyObj.fUnits;
112 fNrColumns = surveyObj.fNrColumns;
113 fColNames = surveyObj.fColNames;
114 fIsValid = surveyObj.fIsValid;
115 fGridUser = surveyObj.fGridUser;
116 TObject *curr = surveyObj.fDataPoints->First();
118 fDataPoints->Add(curr);
119 curr = surveyObj.fDataPoints->After(curr);
126 //_____________________________________________________________________________
127 void AliSurveyObj::AddPoint(AliSurveyPoint* point) {
128 // Adds a point to the TObjArray which containst the list of points
129 fDataPoints->Add(point);
134 //_____________________________________________________________________________
135 Bool_t AliSurveyObj::Connect(const char *gridUrl, const char *user) {
136 // Connects to the grid
138 // If the same "Grid" is alreay active, skip connection
139 if (!gGrid || gridUrl != gGrid->GridUrl() ||
140 (( user != "" ) && ( user != gGrid->GetUser() )) ) {
141 // connection to the Grid
142 AliInfo("\nConnecting to the Grid...");
144 AliInfo(Form("gGrid = %x; GridUrl = %s; gGrid->GridUrl() = %s",
145 gGrid, gridUrl, gGrid->GridUrl()));
146 AliInfo(Form("User = %s; gGrid->GetUser() = %s",
147 user, gGrid->GetUser()));
149 TGrid::Connect(gridUrl,user);
153 AliError("Connection failed!");
160 //_____________________________________________________________________________
161 Bool_t AliSurveyObj::OpenFile(TString openString) {
162 // Opens the file and reads it to a buffer
163 TString storage = "alien://alice.cern.ch";
165 Printf("TFile::Open string: \n -> \"%s\"\n", openString.Data());
167 if (openString.BeginsWith("alien://"))
168 if (!Connect(storage.Data(), fGridUser.Data())) {
169 AliError(Form("Error connecting to GRID"));
173 TFile *file = TFile::Open(openString.Data(), "READ");
175 AliError(Form("Error opening file \"%s\"", openString.Data()));
179 Int_t size = file->GetSize();
181 char *buf = new Char_t[size + 1];
182 memset(buf, '\0', size + 1);
185 if ( file->ReadBuffer(buf, size) ) {
186 AliError("Error reading file contents to buffer!");
189 Printf("%d bytes read!\n", file->GetBytesRead());
200 //_____________________________________________________________________________
201 Bool_t AliSurveyObj::Fill(TString detector, Int_t year, Int_t reportNumber,
202 Int_t reportVersion, TString username) {
203 // Fills the object from a file in the default storage location in AliEn
205 TString baseFolder = "/alice/data/Reference/";
206 TString validDetectors = "ACORDE,BABYFRAME,BACKFRAME,EMCAL,FMD,HMPID,ITS,L3 MAGNET,MUON,MUON ABSORBERS,MUON DIPOLE,PHOS,PMD,SPACEFRAME,SUPERSTRUCTURE,T0,TOF,TPC,TRD,V0,ZDC";
207 TString GRPDetectors = "BABYFRAME,BACKFRAME,L3 MAGNET,SPACEFRAME,MUON DIPOLE,MUON ABSORBERS";
208 TString MUONDetectors = "MUON,SUPERSTRUCTURE";
212 // Check if <detector> is valid
213 TObjArray *dets = validDetectors.Tokenize(',');
214 if (!dets->FindObject(detector)) {
215 AliError(Form("Detector '%s' is not a valid detector/structure!", detector.Data()));
221 // Some "detectors" don't have a folder of their own
222 dets = GRPDetectors.Tokenize(',');
223 if (dets->FindObject(detector)) detector = "GRP";
227 dets = MUONDetectors.Tokenize(',');
228 if (dets->FindObject(detector)) detector = "MUON";
232 // Check if <year>, <reportNumber> and <reportVersion> are valid (roughly)
233 if ((year < 1950) || (reportNumber < 1) || (reportVersion < 1)) {
234 AliError("Invalid parameter values for AliSurveyObj::Fill. (Year, Report Number or Report Version)");
238 // Finally composes the full string
239 TString fullOpenString = "alien://" + baseFolder + detector + "/RawSurvey/";
240 fullOpenString += Form("%d/%d_v%d.txt?filetype=raw", year, reportNumber, reportVersion);
242 // Set the GRID username variable to connect to the GRID
243 fGridUser = username;
245 return OpenFile(fullOpenString);
249 //_____________________________________________________________________________
250 Bool_t AliSurveyObj::FillFromLocalFile(const Char_t* filename) {
251 // Fills the object from a file in a local filesystem
253 TString fullOpenString = "file://" + TString(filename) + "?filetype=raw";
255 return OpenFile(fullOpenString);
259 //_____________________________________________________________________________
260 TString &AliSurveyObj::Sanitize(TString str) {
261 // Cleans up a line of new line and carriage return characters.
262 // (Specially usefull for files created in Windows.)
264 str.Remove(TString::kTrailing, '\r');
265 str.Remove(TString::kTrailing, '\n');
266 str.Remove(TString::kTrailing, '\r');
267 if (!str.IsAscii()) {
268 AliWarning("Warning: Non-ASCII characters!\n");
271 return str.Remove(TString::kBoth, ' ');
275 //_____________________________________________________________________________
276 Bool_t AliSurveyObj::ParseBuffer(const Char_t* buf) {
277 // Parses a character buffer assuming the format defined with the TS/SU
278 // http://aliceinfo/Offline/Activities/Alignment/SurveyInformation.html
280 // If the object is already filled clean it up
281 if (fIsValid) Reset();
283 // Copy the buffer to a TString to use Tokenize
284 TString buffer = TString(buf);
285 TObjArray *lines = buffer.Tokenize('\n');
286 TObjArray *dataLine = NULL; // Used to Tokenize each point/line read
287 TObjArray *colLine = NULL; // Used to Tokenize the column names
289 // Some local variables declarations and initializations
290 const Int_t kFieldCheck = 10;
291 Bool_t check[kFieldCheck];
292 TString tmp_name = "";
293 Float_t tmp_x = 0.0, tmp_y = 0.0, tmp_z = 0.0;
294 Float_t tmp_precX = 0.0, tmp_precY = 0.0, tmp_precZ = 0.0;
295 Char_t tmp_type = '\0';
296 Bool_t tmp_targ = kTRUE;
297 AliSurveyPoint *dp = 0;
298 for (Int_t i = 0; i < kFieldCheck; ++i) check[i] = kFALSE;
300 Int_t nrLines = lines->GetEntries();
301 Printf("Lines in file: %d\n", nrLines);
303 // The main cycle, the buffer is parsed a line at a time
304 TString currLine = "", nextLine = "";
305 for (Int_t i = 0; i < nrLines; ++i) {
308 currLine = ((TObjString *)(lines->At(i)))->GetString().Data();
309 nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : "");
310 currLine = Sanitize(currLine);
311 nextLine = Sanitize(nextLine);
312 // Printf("\n%d: \"\"%s\"\"\"\n", i + 1, currLine.Data());
315 if (0 == currLine.Length()) Printf("Info: Empty line skipped\n\n");
317 // The line contains a keyword
318 else if (currLine.BeginsWith(">") && !nextLine.BeginsWith(">")) {
319 currLine.Remove(TString::kLeading, '>');
320 currLine.Remove(TString::kTrailing, ':');
321 currLine.Remove(TString::kBoth, ' ');
322 nextLine.Remove(TString::kBoth, ' ');
323 // Printf(" -> Field: \"%s\"\n", currLine.Data());
325 if (currLine.BeginsWith("Title", TString::kIgnoreCase)) {
329 } else if (currLine.BeginsWith("Date", TString::kIgnoreCase)) {
330 // Report(measurement) Date
333 } else if (currLine.BeginsWith("Subdetector", TString::kIgnoreCase)) {
334 // Subdetector or structure
335 fDetector = nextLine;
337 } else if (currLine.BeginsWith("Report URL", TString::kIgnoreCase)) {
338 // Report URL in EDMS
339 if (nextLine.BeginsWith("http://edms.cern.ch/document/", TString::kIgnoreCase) ||
340 nextLine.BeginsWith("https://edms.cern.ch/document/", TString::kIgnoreCase)) {
342 nextLine.Remove(TString::kTrailing, '/');
343 nextLine = nextLine(nextLine.Last('/') + 1, nextLine.Length() - nextLine.Last('/') + 1);
345 Int_t sscanf_tmp = 0;
346 if (1 != sscanf(nextLine.Data(), "%d", &sscanf_tmp)) {
347 AliError("Survey text file sintax error! (incorrectly formated Report URL)");
351 fReportNr = nextLine.Atoi();
352 //Printf(" $$ %d $$\n", fReportNr);
355 // URL incorrectly formated
356 AliError("Survey text file sintax error! (incorrectly formated Report URL)");
359 } else if (currLine.BeginsWith("Version", TString::kIgnoreCase)) {
361 if (!nextLine.IsDigit()) {
363 AliError("Survey text file sintax error! (incorrectly formated Report Version)");
366 fVersion = nextLine.Atoi();
368 } else if (currLine.BeginsWith("General Observations", TString::kIgnoreCase)) {
371 // Can be more than 1 line. Loop until another keyword is found
372 while (('>' != nextLine[0]) && (nextLine.Length() > 0) && (i < nrLines)) {
373 fObs += (0 == fObs.Length()) ? nextLine : " / " + nextLine;
375 nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : "");
376 nextLine = Sanitize(nextLine);
378 } else if (currLine.BeginsWith("Coordinate System", TString::kIgnoreCase)) {
380 fCoordSys = nextLine;
382 } else if (currLine.BeginsWith("Units", TString::kIgnoreCase)) {
386 } else if (currLine.BeginsWith("Nr Columns", TString::kIgnoreCase)) {
387 // Number of columns in the "Data" section
388 if (!nextLine.IsDigit()) {
390 AliError("Survey text file sintax error! (incorrectly formated Number of Columns)");
393 fNrColumns = nextLine.Atoi();
395 } else if (currLine.BeginsWith("Column Names", TString::kIgnoreCase)) {
396 // Column names separated by commas
397 fColNames = nextLine;
398 colLine = nextLine.Tokenize(',');
399 if (colLine->GetEntries() != fNrColumns) {
400 AliError("Survey text file sintax error! (Declared number of Columns doesn't match number of column names)");
406 } else if (currLine.BeginsWith("Data", TString::kIgnoreCase)) {
408 while ((nextLine.Length() > 0) && ('>' != nextLine[0])) {
410 // Printf("Data LINE: \"%s\": %d\n", nextLine.Data(), nextLine.Length());
412 // What is the separator used between fields?
413 // The allowed are: comma (','), tab ('\t'), and space (' ')
414 if (fNrColumns == nextLine.CountChar(',') + 1) dataLine = nextLine.Tokenize(',');
415 else if (fNrColumns == nextLine.CountChar('\t') + 1) dataLine = nextLine.Tokenize('\t');
416 else if (fNrColumns == nextLine.CountChar(' ') + 1) dataLine = nextLine.Tokenize(' ');
418 // Error (No separator was found!)
419 AliError("Survey text file syntax error! Error processing data line!");
424 if (dataLine->GetEntries() != fNrColumns) {
425 // The number of columns doesn't match the number specified in the header
426 AliError("Survey text file sintax error! (Number of entries in line is different from declared Number of Columns)");
432 // Reset the bits used to check if all the required fields are present
433 for (Int_t t = 0; t < kFieldCheck; ++t) check[t] = 0;
435 // Process the data line using the column names as index
436 for (Int_t j = 0; j < dataLine->GetEntries(); ++j) {
437 TString cn = ((TObjString *)(colLine->At(j)))->GetString();
438 TString value = ((TObjString *)(dataLine->At(j)))->GetString();
439 if (cn.BeginsWith("Point Name", TString::kIgnoreCase)) {
442 } else if (cn.BeginsWith("X", TString::kIgnoreCase)) {
443 tmp_x = value.Atof();
445 } else if (cn.BeginsWith("Y", TString::kIgnoreCase)) {
446 tmp_y = value.Atof();
448 } else if (cn.BeginsWith("Z", TString::kIgnoreCase)) {
449 tmp_z = value.Atof();
451 } else if (cn.BeginsWith("Precision", TString::kIgnoreCase)) {
452 TString tmpCN = cn(0, cn.First('('));
453 Int_t precLength = TString("Precision").Length();
454 //Printf(" ====== %d ======= %d ====== \n", precLength, tmpCN.Length());
455 //Printf(" ====== %s ======= \n", tmpCN.Data());
456 if (precLength == tmpCN.Length()) {
457 tmp_precX = tmp_precY = tmp_precZ = value.Atof();
460 TString axis = cn(precLength, tmpCN.Length() - precLength);
461 if (axis.Contains('X', TString::kIgnoreCase)) {
462 tmp_precX = value.Atof();
464 } else if (axis.Contains('Y', TString::kIgnoreCase)) {
465 tmp_precY = value.Atof();
467 } else if (axis.Contains('Z', TString::kIgnoreCase)) {
468 tmp_precZ = value.Atof();
471 AliError("Survey text file sintax error! (Precision column name invalid)");
477 } else if (cn.BeginsWith("Point Type", TString::kIgnoreCase)) {
478 tmp_type = value.Data()[0];
480 } else if (cn.BeginsWith("Target Used", TString::kIgnoreCase)) {
481 tmp_targ = (value.Data()[0] == 'Y') ? kTRUE : kFALSE;
485 //Printf("--> %s\n", ((TObjString *)(dataLine->At(j)))->GetString().Data());
488 // Check if all the mandatory fields exist
489 Bool_t res = kTRUE, precInd = kTRUE;
492 if (kFALSE == check[5]) {
497 // Individual axis precisions
498 for (Int_t t = 7; t < 10; ++t) precInd &= check[t];
499 if ((kFALSE == check[6]) && (kTRUE == precInd)) check[6] = kTRUE;
501 for (Int_t t = 0; t < kFieldCheck - 3; ++t) {
502 //Printf("RES(%d): %d\n", t, check[t]);
506 dp = new AliSurveyPoint(tmp_name, tmp_x, tmp_y, tmp_z, tmp_precX, tmp_precY, tmp_precZ, tmp_type, tmp_targ);
510 AliError("Parsing error processing data line!");
519 nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : "");
520 nextLine = Sanitize(nextLine);
524 AliError("Survey text file sintax error!");
534 //_____________________________________________________________________________
535 void AliSurveyObj::Reset() {
536 // Resets the AliSurveyObj to a clean object.
537 // Used if the same object is filled more than once
540 for (Int_t i = 0; i < fDataPoints->GetEntries(); ++i) delete fDataPoints->At(i);
541 fDataPoints->Delete();
547 fURL = "http://edms.cern.ch/";
556 fDataPoints = new TObjArray(1);
557 fDataPoints->SetOwner(kTRUE);