X-Git-Url: http://git.uio.no/git/?p=u%2Fmrichter%2FAliRoot.git;a=blobdiff_plain;f=STEER%2FAliSurveyObj.cxx;h=0afda085ef5e58b4d677ce22c109f98e122c3e01;hp=39749650b0375d9e49a774dd67c37919fa5b50d1;hb=f7ce7a372c80bb893d8bab14717fdf0293b98156;hpb=573b6a5a77cea7a9fed2a957920fce1f5b3fac96 diff --git a/STEER/AliSurveyObj.cxx b/STEER/AliSurveyObj.cxx index 39749650b03..0afda085ef5 100644 --- a/STEER/AliSurveyObj.cxx +++ b/STEER/AliSurveyObj.cxx @@ -23,20 +23,28 @@ #include "AliSurveyObj.h" //ROOT includes -#include "TROOT.h" -#include "Riostream.h" #include "TObjArray.h" #include "TGrid.h" +#include "TGridResult.h" #include "TFile.h" #include "TObjString.h" //AliROOT includes #include "AliLog.h" - -//System includes -//#include //for sleep(3); // not used anymore!? +#include "AliSurveyPoint.h" ClassImp(AliSurveyObj) + + +const TString AliSurveyObj::fgkStorage = "alien://alice.cern.ch"; +const TString AliSurveyObj::fgkBaseFolder = "/alice/data/Reference"; +const TString AliSurveyObj::fgkValidDetectors = "ACORDE,BABYFRAME,BACKFRAME,\ +EMCAL,FMD,HMPID,ITS,L3 MAGNET,MUON,MUON ABSORBERS,MUON DIPOLE,PHOS,PMD,\ +SPACEFRAME,SUPERSTRUCTURE,T0,TOF,TPC,TRD,VZERO,ZDC,GRP"; +const TString AliSurveyObj::fgkGRPDetectors = "BABYFRAME,BACKFRAME,L3 MAGNET,\ +SPACEFRAME,MUON DIPOLE,MUON ABSORBERS,GRP"; +const TString AliSurveyObj::fgkMUONDetectors = "MUON,SUPERSTRUCTURE"; + //_____________________________________________________________________________ AliSurveyObj::AliSurveyObj(): @@ -53,6 +61,7 @@ AliSurveyObj::AliSurveyObj(): fNrColumns(-1), fColNames(""), fIsValid(kFALSE), + fGridUser(""), fDataPoints(new TObjArray(1)) { // constructor @@ -63,7 +72,10 @@ AliSurveyObj::AliSurveyObj(): //_____________________________________________________________________________ AliSurveyObj::~AliSurveyObj() { //destructor - + if (fDataPoints) { + fDataPoints->Delete(); + fDataPoints = 0; + } } @@ -82,6 +94,7 @@ AliSurveyObj::AliSurveyObj(const AliSurveyObj& surveyObj): fNrColumns(surveyObj.fNrColumns), fColNames(surveyObj.fColNames), fIsValid(surveyObj.fIsValid), + fGridUser(surveyObj.fGridUser), fDataPoints(new TObjArray(1)) { // copy constructor @@ -92,6 +105,7 @@ AliSurveyObj::AliSurveyObj(const AliSurveyObj& surveyObj): } } + //_____________________________________________________________________________ AliSurveyObj& AliSurveyObj::operator=(const AliSurveyObj& surveyObj) { @@ -109,20 +123,20 @@ AliSurveyObj& AliSurveyObj::operator=(const AliSurveyObj& surveyObj) fNrColumns = surveyObj.fNrColumns; fColNames = surveyObj.fColNames; fIsValid = surveyObj.fIsValid; - + fGridUser = surveyObj.fGridUser; TObject *curr = surveyObj.fDataPoints->First(); while (curr != 0) { fDataPoints->Add(curr); curr = surveyObj.fDataPoints->After(curr); } } - return *this; } //_____________________________________________________________________________ void AliSurveyObj::AddPoint(AliSurveyPoint* point) { + // Adds a point to the TObjArray which containst the list of points fDataPoints->Add(point); return; } @@ -130,36 +144,41 @@ void AliSurveyObj::AddPoint(AliSurveyPoint* point) { //_____________________________________________________________________________ Bool_t AliSurveyObj::Connect(const char *gridUrl, const char *user) { - - // if the same Grid is alreay active, skip connection - if ( !gGrid || gridUrl != gGrid->GridUrl() || - (( user != "" ) && ( user != gGrid->GetUser() )) ) { - // connection to the Grid - AliInfo("\nConnecting to the Grid..."); - if(gGrid){ - AliInfo(Form("gGrid = %x; GridUrl = %s; gGrid->GridUrl() = %s", - gGrid, gridUrl, gGrid->GridUrl())); - AliInfo(Form("User = %s; gGrid->GetUser() = %s", - user, gGrid->GetUser())); - } - TGrid::Connect(gridUrl,user); - } + // Connects to the grid + + // If the same "Grid" is alreay active, skip connection + if (!gGrid || gridUrl != gGrid->GridUrl() || + (( strcmp(user,"") ) && ( strcmp(user,gGrid->GetUser()) )) ) { + // connection to the Grid + AliInfo("\nConnecting to the Grid..."); + if (gGrid) { + AliInfo(Form("gGrid = %p; GridUrl = %s; gGrid->GridUrl() = %s", + gGrid, gridUrl, gGrid->GridUrl())); + AliInfo(Form("User = %s; gGrid->GetUser() = %s", + user, gGrid->GetUser())); + } + TGrid::Connect(gridUrl,user); + } - if(!gGrid) { - AliError("Connection failed!"); - return kFALSE; - } - return kTRUE; + if(!gGrid) { + AliError("Connection failed!"); + return kFALSE; + } + return kTRUE; } //_____________________________________________________________________________ Bool_t AliSurveyObj::OpenFile(TString openString) { - TString storage = "alien://alice.cern.ch"; + // Opens the file and reads it to a buffer - Printf("TFile::Open string: \n -> \"%s\"\n", openString.Data()); + AliInfo(Form("Opening file \"%s\"\n for survey data", openString.Data())); - if (openString.BeginsWith("alien://")) Connect(storage.Data(), "rsilva"); + if (openString.BeginsWith("alien://")) + if (!Connect(fgkStorage.Data(), fGridUser.Data())) { + AliError(Form("Error connecting to GRID")); + return kFALSE; + } TFile *file = TFile::Open(openString.Data(), "READ"); if ( !file ) { @@ -169,59 +188,364 @@ Bool_t AliSurveyObj::OpenFile(TString openString) { Int_t size = file->GetSize(); - char *buf = new Char_t[size]; - memset(buf, '\0', size); - - //--size; + char *buf = new Char_t[size + 1]; + memset(buf, '\0', size + 1); file->Seek(0); if ( file->ReadBuffer(buf, size) ) { AliError("Error reading file contents to buffer!"); return kFALSE; } - - // Printf("%d bytes read!\n", size); - Printf("%d bytes read!\n", file->GetBytesRead()); + AliInfo(Form("%lld bytes read!\n", file->GetBytesRead())); - // Printf("->\n%s\n<- ", buf); - - // Printf("%d AQUI!\n", size); - - ParseBuffer(buf); + Bool_t goodParsing = ParseBuffer(buf); file->Close(); delete[] buf; - return kTRUE; + return goodParsing; +} + + +//_____________________________________________________________________________ +Bool_t AliSurveyObj::FillFromLocalFile(const Char_t* filename) { + // Fills the object from a file in a local filesystem + + TString fullOpenString = "file://" + TString(filename) + "?filetype=raw"; + + return OpenFile(fullOpenString); } +//_____________________________________________________________________________ +Bool_t AliSurveyObj::IsValidDetector(TString detector) const { + // Checks if the detector name is valid + + detector.ToUpper(); + + TObjArray *dets = fgkValidDetectors.Tokenize(','); + TObject *found = dets->FindObject(detector); + dets->Delete(); + dets = 0; + + if (!found) return kFALSE; + else return kTRUE; +} + + +//_____________________________________________________________________________ +TString AliSurveyObj::RealFolderName(TString detector) const { + // Returns the actual folder name for a given detector + // Some "detectors" don't have a folder of their own + + detector.ToUpper(); + TString folderName = detector; + + TObjArray *dets = fgkGRPDetectors.Tokenize(','); + if (dets->FindObject(detector)) folderName = "GRP"; + dets->Delete(); + dets = 0; + + dets = fgkMUONDetectors.Tokenize(','); + if (dets->FindObject(detector)) folderName = "MUON"; + dets->Delete(); + + + + dets = 0; + + return folderName; +} + +//_____________________________________________________________________________ +Bool_t AliSurveyObj::Fill(TString detector, Int_t reportNumber, + TString username) { + // Fills the object from a file in the default storage location in AliEn. + // The highest version available is selected. + + return Fill(detector, reportNumber, -1, username); +} //_____________________________________________________________________________ Bool_t AliSurveyObj::Fill(TString detector, Int_t reportNumber, - Int_t reportVersion) { - TString baseFolder = "/alice/cern.ch/user/r/rsilva/"; + Int_t reportVersion, TString username) { + // Fills the object from a file in the default storage location in AliEn. + // A specific version is selected. + + detector.ToUpper(); + + // Check if is valid + if (!IsValidDetector(detector)) { + AliWarning(Form("Detector '%s' is not a valid detector/structure!", detector.Data())); + return kFALSE; + } + + // Some "detectors" don't have a folder of their own + // TString detectorFolder = RealFolderName(detector); + + // Check if , and are valid (roughly) + if ((reportNumber < 1) || (reportVersion < -1) || (0 == reportVersion)) { + AliError("Invalid parameter values for AliSurveyObj::Fill. (Report Number or Report Version)"); + return kFALSE; + } + + // Check if the fGridUser is set, or specified + if (username.Length() > 0) SetGridUser(username); + else if (0 == fGridUser.Length()) { + AliError("GRID username not specified and not previously set!"); + return kFALSE; + } + + // Query AliEn for the available reports + TGridResult *res = QueryReports(detector, -1, reportNumber, reportVersion); + if (!res) AliError(Form("Error querying AliEn for detector '%s', \ + report number '%d' and report version '%d'.", + detector.Data(), reportNumber, reportVersion)); + Int_t numberEntries = res->GetEntries(); + if (0 == numberEntries) { + AliError(Form("No report found for detector '%s', report number '%d' and report version '%d'", + detector.Data(), reportNumber, reportVersion)); + return kFALSE; + } + + TString fileNamePath = ""; + if (1 == numberEntries) fileNamePath = res->GetFileNamePath(0); + else if (numberEntries > 1) { + TString higherVerFNP = res->GetFileNamePath(0); + Int_t lastYear = FileNamePathToReportYear(higherVerFNP); + for (Int_t i = 1; i < numberEntries; ++i) { + TString currFNP = res->GetFileNamePath(i); + if (FileNamePathToReportVersion(currFNP) > + FileNamePathToReportVersion(higherVerFNP)) higherVerFNP = currFNP; + if (lastYear != FileNamePathToReportYear(currFNP)) + 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."); + } + fileNamePath = higherVerFNP; + } - TString fullOpenString = "alien://" + baseFolder + detector + '/'; - fullOpenString += Form("%d_v%d.txt?filetype=raw", reportNumber, reportVersion); - // !Still need to check it's a valid path before actually using it + TString fullOpenString = "alien://" + fileNamePath + "?filetype=raw"; + /* + // Finally composes the full string + TString fullOpenString = "alien://" + fgkBaseFolder + "/" + detectorFolder + "/RawSurvey/"; + fullOpenString += Form("%d/%d_v%d.txt?filetype=raw", year, reportNumber, reportVersion); + */ return OpenFile(fullOpenString); } //_____________________________________________________________________________ -Bool_t AliSurveyObj::FillFromLocalFile(const Char_t* filename) { - TString fullOpenString = "file://" + TString(filename) + "?filetype=raw"; +TString AliSurveyObj::FileNamePathToDetector(TString filename) const { + // Get the report number from the complete path in the format: + // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt + + TString ret = ""; + + if (filename.Length() > fgkBaseFolder.Length()) { + ret = filename.Remove(0, fgkBaseFolder.Length()); + ret.Remove(TString::kLeading, '/'); + ret = ret(0, ret.First('/')); + if (!IsValidDetector(ret)) ret = ""; + } + return ret; +} - return OpenFile(fullOpenString); +///alice/cern.ch/user/r/rsilva/TRD/RawSurvey/2007/.816582_v2.txt/v1.0 + +//_____________________________________________________________________________ +Int_t AliSurveyObj::FileNamePathToReportYear(TString filename) const { + // Get the report year from the complete path in the format: + // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt + + TString ret = ""; + + if (filename.Length() > fgkBaseFolder.Length()) { + ret = filename.Remove(0, fgkBaseFolder.Length()); + ret.Remove(TString::kLeading, '/'); + Int_t beg = ret.First('/') + TString("RawSurvey/").Length() + 1; + ret = ret(beg, ret.Last('/') - beg); + return ret.Atoi(); + } + return -1; +} + + +//_____________________________________________________________________________ +Int_t AliSurveyObj::FileNamePathToReportNumber(TString filename) const { + // Get the report number from the complete path in the format: + // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt + + TString ret = ""; + + if (filename.Length() > fgkBaseFolder.Length()) { + ret = filename.Remove(0, fgkBaseFolder.Length()); + ret.Remove(TString::kLeading, '/'); + if ((ret.CountChar('/') > 3) || (ret.CountChar('.') > 1)) { + AliWarning("Error getting the Report Number from the filename path!"); + return -1; + } + ret = ret(ret.Last('/') + 1 , ret.Last('_') - ret.Last('/') - 1); + return ret.Atoi(); + } + AliWarning("Error getting the Report Number from the filename path!"); + return -1; +} + + +//_____________________________________________________________________________ +Int_t AliSurveyObj::FileNamePathToReportVersion(TString filename) const { + // Get the report version from the complete path in the format: + // /alice/data/Reference/HMPID/RawSurvey/2006/781282_v1.txt + + TString ret = ""; + + if (filename.Length() > fgkBaseFolder.Length()) { + ret = filename.Remove(0, fgkBaseFolder.Length()); + ret.Remove(TString::kLeading, '/'); + if ((ret.CountChar('/') > 3) || (ret.CountChar('.') > 1)) { + AliWarning("Error getting the Report Version from the filename path!"); + return -1; + } + ret = ret(ret.Last('_') + 1 + 1 , ret.Last('.') - ret.Last('_') - 1 - 1); + return ret.Atoi(); + } + AliWarning("Error getting the Report Version from the filename path!"); + return -1; +} + + +//_____________________________________________________________________________ +void AliSurveyObj::ListValidDetectors() { + // List the valid detector names + Printf("Listing all valid detectors:\n"); + TObjArray *dets = fgkValidDetectors.Tokenize(','); + for (int i = 0; i < dets->GetEntries(); ++i) + Printf("%s", ((TObjString *) dets->At(i))->GetString().Data()); + dets->Delete(); + dets = 0; + Printf("Some reports are stored in more general folders.\n" + "These reports can be opened using either name, the original or the\n" + "folder name. Example: 'SPACEFRAME' or 'GRP' are both valid when\n" + "opening a report for the Spaceframe.\n\n" + "Detectors stored in 'MUON' folder:"); + dets = fgkMUONDetectors.Tokenize(','); + for (int i = 0; i < dets->GetEntries(); ++i) + Printf("%s", ((TObjString *) dets->At(i))->GetString().Data()); + dets->Delete(); + dets = 0; + Printf("Detectors stored in 'GRP' folder:"); + dets = fgkGRPDetectors.Tokenize(','); + for (int i = 0; i < dets->GetEntries(); ++i) + Printf("%s", ((TObjString *) dets->At(i))->GetString().Data()); + dets->Delete(); + dets = 0; + return; +} + + +//_____________________________________________________________________________ +TGridResult * AliSurveyObj::QueryReports(TString detector, Int_t year, + Int_t reportNumber, + Int_t reportVersion) { + // Queries AliEn for existing reports matching the specified conditions + TString lsArg = fgkBaseFolder; + + TString detectorFolder = ""; + if (detector.Length() > 0) { + detector.ToUpper(); + // Check if is valid + if (!IsValidDetector(detector)) { + AliError(Form("Detector '%s' is not a valid detector/structure!", + detector.Data())); + return 0; + } + // Some "detectors" don't have a folder of their own + detectorFolder = "/" + RealFolderName(detector); + } else detectorFolder = "/*"; + + lsArg += detectorFolder + "/RawSurvey"; + + TString yearFolder = ""; + if (year > 1950) yearFolder.Form("/%d", year); + else yearFolder = "/*"; + + TString reportFolder = ""; + if (reportNumber > 0) reportFolder.Form("/%d", reportNumber); + else reportFolder = "/*"; + + TString versionFolder = ""; + if (reportVersion > 0) versionFolder.Form("_v%d", reportVersion); + else versionFolder = "_v*"; + + lsArg += yearFolder + reportFolder + versionFolder + ".txt"; + + AliInfo(Form("\nLooking for: %s \n", lsArg.Data())); + + // Check if fGridUser is set and Connect to AliEn + if (0 == fGridUser.Length()) { + AliError("To use this method it's necessary to call SetGridUser(...) in advance."); + return 0; + } else if (!Connect(fgkStorage.Data(), fGridUser.Data())) { + AliError(Form("Error connecting to GRID")); + return 0; + } + return gGrid->Ls(lsArg); +} + + +//_____________________________________________________________________________ +Int_t AliSurveyObj::ListReports(TString detector, Int_t year, + Int_t reportNumber, + Int_t reportVersion) { + // Lists all available reports matching the specified conditions + // Returns the number of reports found + + TGridResult *res = QueryReports(detector, year, reportNumber, reportVersion); + + if (0 == res) { + AliError("Query failed."); + return 0; + } + + TString fn = ""; + Int_t numberEntries = res->GetEntries(); + + if (numberEntries > 0) { + Printf("%d reports found:", numberEntries); + for (int i = 0; i < res->GetEntries(); ++i) { + fn = res->GetFileNamePath(i); + Printf("Detector:%s\tYear:%d\tEDMS Report Number:%d\tVersion:%d", + FileNamePathToDetector(fn).Data(), + FileNamePathToReportYear(fn), + FileNamePathToReportNumber(fn), + FileNamePathToReportVersion(fn)); + } + delete res; + return numberEntries; + } else { + AliInfo("No results found for the requested query."); + delete res; + return 0; + } +} + + +//_____________________________________________________________________________ +void AliSurveyObj::SetGridUser(TString username){ + // Set the username used to connect to the GRID + fGridUser = username; + return; } //_____________________________________________________________________________ TString &AliSurveyObj::Sanitize(TString str) { + // Cleans up a line of new line and carriage return characters. + // (Specially usefull for files created in Windows.) + str.Remove(TString::kTrailing, '\r'); str.Remove(TString::kTrailing, '\n'); str.Remove(TString::kTrailing, '\r'); + if (!str.IsAscii()) { AliWarning("Warning: Non-ASCII characters!\n"); str = ""; @@ -232,41 +556,71 @@ TString &AliSurveyObj::Sanitize(TString str) { //_____________________________________________________________________________ Bool_t AliSurveyObj::ParseBuffer(const Char_t* buf) { + // Parses a character buffer assuming the format defined with the TS/SU + // http://aliceinfo/Offline/Activities/Alignment/SurveyInformation.html + + // If the object is already filled clean it up + if (fIsValid) Reset(); + + // Copy the buffer to a TString to use Tokenize TString buffer = TString(buf); - TObjArray *lines = buffer.Tokenize('\n'); - TObjArray *dataLine = NULL; // Used to Tokenize each point read + TObjArray *linesRaw = buffer.Tokenize('\n'); + // replace the array of lines with an array of sanitized lines + // in the process we remove empty lines, particularly disturbing + // in case of dos fileformat + TString oneLine = ""; + TObjString* oneLineObj = 0; + TObjArray *lines = new TObjArray(); + for(Int_t i=0; iGetEntries(); i++) + { + oneLine = ((TObjString *)(linesRaw->At(i)))->GetString().Data(); + oneLine = Sanitize(oneLine); + if (oneLine.Length() == 0) continue; + oneLineObj = new TObjString(oneLine); + lines->Add(oneLineObj); + } + + linesRaw->Delete(); + delete linesRaw; + linesRaw = NULL; + + TObjArray *dataLine = NULL; // Used to Tokenize each point/line read TObjArray *colLine = NULL; // Used to Tokenize the column names + // Some local variables declarations and initializations const Int_t kFieldCheck = 10; - Bool_t check[kFieldCheck]; - TString tmp_name = ""; - Float_t tmp_x = 0.0, tmp_y = 0.0, tmp_z = 0.0; - Float_t tmp_precX = 0.0, tmp_precY = 0.0, tmp_precZ = 0.0; - Char_t tmp_type = '\0'; - Bool_t tmp_targ = kTRUE; - AliSurveyPoint *dp = 0; - + Bool_t check[kFieldCheck]; // used to check that mandatory column names are not missing for (Int_t i = 0; i < kFieldCheck; ++i) check[i] = kFALSE; + TString tmpname = ""; + Float_t tmpx = 0.0, tmpy = 0.0, tmpz = 0.0; + Float_t tmpprecX = -1., tmpprecY = -1., tmpprecZ = -1.; + Char_t tmptype = '\0'; + Bool_t tmptarg = kTRUE; + AliSurveyPoint *dp = 0; + TString *orderedValues[9] = {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0}; + TString value[9]; Int_t nrLines = lines->GetEntries(); Printf("Lines in file: %d\n", nrLines); + // The main cycle, the buffer is parsed a line at a time TString currLine = "", nextLine = ""; for (Int_t i = 0; i < nrLines; ++i) { + + // Get the next line currLine = ((TObjString *)(lines->At(i)))->GetString().Data(); nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : ""); - currLine = Sanitize(currLine); - nextLine = Sanitize(nextLine); - //Printf("\n%d: \"\"%s\"\"\"\n", i + 1, currLine.Data()); + // Printf("%d: \"%s\"", i, currLine.Data()); + // Printf("%d: \"%s\"\n", i+1, nextLine.Data()); - if (0 == currLine.Length()) { - Printf("Info: Empty line skipped\n\n"); - } else if (currLine.BeginsWith(">") && !nextLine.BeginsWith(">")) { + // The line contains a keyword + if (currLine.BeginsWith(">") && !nextLine.BeginsWith(">")) { currLine.Remove(TString::kLeading, '>'); currLine.Remove(TString::kTrailing, ':'); currLine.Remove(TString::kBoth, ' '); nextLine.Remove(TString::kBoth, ' '); - // Printf(" -> Field: \"%s\"\n", currLine.Data()); + AliDebug(2, Form(" -> field line: \"%s\"\n", currLine.Data())); + AliDebug(2, Form(" -> value line: \"%s\"\n", nextLine.Data())); if (currLine.BeginsWith("Title", TString::kIgnoreCase)) { // Report Title @@ -288,179 +642,269 @@ Bool_t AliSurveyObj::ParseBuffer(const Char_t* buf) { nextLine.Remove(TString::kTrailing, '/'); nextLine = nextLine(nextLine.Last('/') + 1, nextLine.Length() - nextLine.Last('/') + 1); - Printf("## %s ##\n", nextLine.Data()); - Int_t sscanf_tmp = 0; - //if (!nextLine.IsDigit()) { - if (1 != sscanf(nextLine.Data(), "%d", &sscanf_tmp)) { - AliError("Survey text file sintax error! (incorrectly formated Report URL)"); + if (!nextLine.IsDigit()) { + AliError("Survey text file sintax error! (incorrectly formatted Report URL)"); + AliError(Form("Wrong report number string: \"%s\"",nextLine.Data())); lines->Delete(); + delete lines; lines = NULL; return kFALSE; } fReportNr = nextLine.Atoi(); //Printf(" $$ %d $$\n", fReportNr); ++i; - } else { // URL incorrectly formated - AliError("Survey text file sintax error! (incorrectly formated Report URL)"); + } else { + // URL incorrectly formatted + AliError("Survey text file sintax error! (incorrectly formatted Report URL)"); return kFALSE; } } else if (currLine.BeginsWith("Version", TString::kIgnoreCase)) { + // Report version if (!nextLine.IsDigit()) { lines->Delete(); - AliError("Survey text file sintax error! (incorrectly formated Report Version)"); + delete lines; lines = NULL; + AliError("Survey text file sintax error! (incorrectly formatted Report Version)"); return kFALSE; } fVersion = nextLine.Atoi(); ++i; } else if (currLine.BeginsWith("General Observations", TString::kIgnoreCase)) { + // Observations fObs = ""; - while (('>' != nextLine[0]) && nextLine.Length() > 0) { + // Can be more than 1 line. Loop until another keyword is found + while (('>' != nextLine[0]) && (nextLine.Length() > 0) && (i < nrLines)) { fObs += (0 == fObs.Length()) ? nextLine : " / " + nextLine; ++i; nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : ""); - nextLine = Sanitize(nextLine); } - // Printf("->%s<-\n", fObs.Data()); } else if (currLine.BeginsWith("Coordinate System", TString::kIgnoreCase)) { + // Coordinate System fCoordSys = nextLine; ++i; } else if (currLine.BeginsWith("Units", TString::kIgnoreCase)) { + // Measurement Unit fUnits = nextLine; ++i; } else if (currLine.BeginsWith("Nr Columns", TString::kIgnoreCase)) { + // Number of columns in the "Data" section if (!nextLine.IsDigit()) { lines->Delete(); - AliError("Survey text file sintax error! (incorrectly formated Number of Columns)"); + delete lines; lines = NULL; + AliError("Survey text file sintax error! (incorrectly formatted Number of Columns)"); return kFALSE; } fNrColumns = nextLine.Atoi(); ++i; } else if (currLine.BeginsWith("Column Names", TString::kIgnoreCase)) { + // Column names separated by commas fColNames = nextLine; colLine = nextLine.Tokenize(','); if (colLine->GetEntries() != fNrColumns) { AliError("Survey text file sintax error! (Declared number of Columns doesn't match number of column names)"); colLine->Delete(); lines->Delete(); + delete lines; lines = NULL; return kFALSE; } ++i; - } else if (currLine.BeginsWith("Data", TString::kIgnoreCase)) { - while ((nextLine.Length() > 0) && ('>' != nextLine[0])) { - Printf("Data LINE: \"%s\": %d\n", nextLine.Data(), nextLine.Length()); - if (2 == nextLine.Length()) for(Int_t g = 0; g < 2; ++g) Printf("'%c'", nextLine[g]); - - if (fNrColumns == nextLine.CountChar(' ') + 1) dataLine = nextLine.Tokenize(' '); - else if (fNrColumns == nextLine.CountChar(',') + 1) dataLine = nextLine.Tokenize(','); - else if (fNrColumns == nextLine.CountChar('\t') + 1) dataLine = nextLine.Tokenize('\t'); - else { - //Error - AliError("Survey text file syntax error! Error processing data line!"); - lines->Delete(); - return kFALSE; - } - - if (dataLine->GetEntries() != fNrColumns) { - AliError("Survey text file sintax error! (Number of entries in line is different from declared Number of Columns)"); - dataLine->Delete(); - lines->Delete(); - return kFALSE; - } - - for (Int_t t = 0; t < kFieldCheck; ++t) check[t] = 0; - - for (Int_t j = 0; j < dataLine->GetEntries(); ++j) { - TString cn = ((TObjString *)(colLine->At(j)))->GetString(); - TString value = ((TObjString *)(dataLine->At(j)))->GetString(); - if (cn.BeginsWith("Point Name", TString::kIgnoreCase)) { - tmp_name = value; - check[0] = kTRUE; - } else if (cn.BeginsWith("X", TString::kIgnoreCase)) { - tmp_x = value.Atof(); - check[1] = kTRUE; - } else if (cn.BeginsWith("Y", TString::kIgnoreCase)) { - tmp_y = value.Atof(); - check[2] = kTRUE; - } else if (cn.BeginsWith("Z", TString::kIgnoreCase)) { - tmp_z = value.Atof(); - check[3] = kTRUE; - } else if (cn.BeginsWith("Precision", TString::kIgnoreCase)) { - TString tmpCN = cn(0, cn.First('(')); - Int_t precLength = TString("Precision").Length(); - //Printf(" ====== %d ======= %d ====== \n", precLength, tmpCN.Length()); - //Printf(" ====== %s ======= \n", tmpCN.Data()); - if (precLength == tmpCN.Length()) { - tmp_precX = tmp_precY = tmp_precZ = value.Atof(); - check[6] = kTRUE; - } else { - TString axis = cn(precLength, tmpCN.Length() - precLength); - if (axis.Contains('X', TString::kIgnoreCase)) { - tmp_precX = value.Atof(); + + // booleans to track if precision for 1 axis is defined in more than one column + Bool_t prX = kFALSE; + Bool_t prY = kFALSE; + Bool_t prZ = kFALSE; + + for (Int_t j = 0; j < fNrColumns; ++j) { + TString cn = ((TObjString *)(colLine->At(j)))->GetString(); + if (cn.BeginsWith("Point Name", TString::kIgnoreCase)) { + orderedValues[0] = &value[j]; + check[0] = kTRUE; + } else if (cn.BeginsWith("X", TString::kIgnoreCase)) { + orderedValues[1] = &value[j]; + check[1] = kTRUE; + } else if (cn.BeginsWith("Y", TString::kIgnoreCase)) { + orderedValues[2] = &value[j]; + check[2] = kTRUE; + } else if (cn.BeginsWith("Z", TString::kIgnoreCase)) { + orderedValues[3] = &value[j]; + check[3] = kTRUE; + } else if (cn.BeginsWith("Precision", TString::kIgnoreCase)) { + TString tmpCN = cn(0, cn.First('(')); + Int_t precLength = TString("Precision").Length(); + if (precLength == tmpCN.Length()) { + if(!orderedValues[6]){ + orderedValues[6] = &value[j]; + check[6] = kTRUE; + }else{ + AliWarning("Global precision will not be used for X axis"); + } + if(!orderedValues[7]){ + orderedValues[7] = &value[j]; + check[7] = kTRUE; + }else{ + AliWarning("Global precision will not be used for Y axis"); + } + if(!orderedValues[8]){ + orderedValues[8] = &value[j]; + check[8] = kTRUE; + }else{ + AliWarning("Global precision will not be used for Z axis"); + } + } else { + Bool_t orXYZ = kFALSE; + TString axis = cn(precLength, tmpCN.Length() - precLength); + if (axis.Contains('X', TString::kIgnoreCase)) { + if(!prX){ + orderedValues[6] = &value[j]; + check[6] = kTRUE; + orXYZ = kTRUE; + prX = kTRUE; + }else{ + AliError("Precision for X axis was already set!"); + return kFALSE; + } + } + if (axis.Contains('Y', TString::kIgnoreCase)) { + if(!prY){ + orderedValues[7] = &value[j]; check[7] = kTRUE; - } else if (axis.Contains('Y', TString::kIgnoreCase)) { - tmp_precY = value.Atof(); + orXYZ = kTRUE; + prY = kTRUE; + }else{ + AliError("Precision for Y axis was already set!"); + return kFALSE; + } + } + if (axis.Contains('Z', TString::kIgnoreCase)) { + if(!prZ){ + orderedValues[8] = &value[j]; check[8] = kTRUE; - } else if (axis.Contains('Z', TString::kIgnoreCase)) { - tmp_precZ = value.Atof(); - check[9] = kTRUE; - } else { - AliError("Survey text file sintax error! (Precision column name invalid)"); - dataLine->Delete(); - lines->Delete(); + orXYZ = kTRUE; + prZ = kTRUE; + }else{ + AliError("Precision for Z axis was already set!"); return kFALSE; } } - } else if (cn.BeginsWith("Point Type", TString::kIgnoreCase)) { - tmp_type = value.Data()[0]; - check[4] = kTRUE; - } else if (cn.BeginsWith("Target Used", TString::kIgnoreCase)) { - tmp_targ = (value.Data()[0] == 'Y') ? kTRUE : kFALSE; - check[5] = kTRUE; + if(!orXYZ) + { + AliError("Survey text file sintax error: precision column name does not refer to any axis!"); + return kFALSE; + } } - - //Printf("--> %s\n", ((TObjString *)(dataLine->At(j)))->GetString().Data()); - } - Bool_t res = kTRUE, precInd = kTRUE; - - // Target - if (kFALSE == check[5]) { - tmp_targ = kTRUE; + } else if (cn.BeginsWith("Point Type", TString::kIgnoreCase)) { + orderedValues[4] = &value[j]; + check[4] = kTRUE; + } else if (cn.BeginsWith("Target Used", TString::kIgnoreCase)) { + orderedValues[5] = &value[j]; check[5] = kTRUE; } - - // Individual axis precisions - for (Int_t t = 7; t < 10; ++t) precInd &= check[t]; - if ((kFALSE == check[6]) && (kTRUE == precInd)) check[6] = kTRUE; + } - for (Int_t t = 0; t < kFieldCheck - 3; ++t) { - //Printf("RES(%d): %d\n", t, check[t]); - res &= check[t]; + // Check if all the mandatory fields exist in the line with column names + if(!check[0]){ + AliError("Missing mandatory column \"Point Name\"!"); + return kFALSE; + } + if(!(check[1]&&check[2]&&check[3])){ + AliError("Missing one or more mandatory columns for coordinates \"X\",\"Y\",\"Z\""); + return kFALSE; + } + if(!check[4]){ + AliError("Missing mandatory column \"Point Type\"!"); + return kFALSE; + } + if(!(check[6]&&check[7]&&check[8])){ + AliError("Missing one or more mandatory columns for precision along \"X\",\"Y\",\"Z\" axes"); + return kFALSE; + } + + } else if (currLine.BeginsWith("Data", TString::kIgnoreCase)) { + // Data section! + while ((nextLine.Length() > 0) && ('>' != nextLine[0])) { + + // Printf("Data LINE: \"%s\": %d\n", nextLine.Data(), nextLine.Length()); + + // What is the separator used between fields? + // The allowed are: comma (','), tab ('\t'), and space (' ') + if (fNrColumns == nextLine.CountChar(',') + 1) dataLine = nextLine.Tokenize(','); + else if (fNrColumns == nextLine.CountChar('\t') + 1) dataLine = nextLine.Tokenize('\t'); + else if (fNrColumns == nextLine.CountChar(' ') + 1) dataLine = nextLine.Tokenize(' '); + else { + // Error (No separator was found!) + AliError("Survey text file syntax error! Error processing data line!"); + lines->Delete(); + delete lines; lines = NULL; + return kFALSE; } - if (kTRUE == res) { - dp = new AliSurveyPoint(tmp_name, tmp_x, tmp_y, tmp_z, tmp_precX, tmp_precY, tmp_precZ, tmp_type, tmp_targ); - dp->PrintPoint(); - AddPoint(dp); - } else { - AliError("Parsing error processing data line!"); + + if (dataLine->GetEntries() != fNrColumns) { + // The number of columns doesn't match the number specified in the header + AliError("Survey text file sintax error! (Number of entries in line is different from number of Columns)"); dataLine->Delete(); lines->Delete(); + delete lines; lines = NULL; return kFALSE; } - + + // Process the data line using the column names as index + for (Int_t j = 0; j < dataLine->GetEntries(); ++j) { + value[j] = ((TObjString *)(dataLine->At(j)))->GetString(); + } + tmpname = *orderedValues[0]; + tmpx = orderedValues[1]->Atof(); + tmpy = orderedValues[2]->Atof(); + tmpz = orderedValues[3]->Atof(); + tmpprecX = orderedValues[6]->Atof(); + tmpprecY = orderedValues[7]->Atof(); + tmpprecZ = orderedValues[8]->Atof(); + tmptype = orderedValues[4]->Data()[0]; + if(orderedValues[5]) tmptarg = (orderedValues[5]->Data()[0] == 'Y') ? kTRUE : kFALSE; + + dp = new AliSurveyPoint(tmpname, tmpx, tmpy, tmpz, tmpprecX, tmpprecY, tmpprecZ, tmptype, tmptarg); + if(AliLog::GetDebugLevel("","AliSurveyObj")>1) dp->PrintPoint(); + AddPoint(dp); + dataLine->Delete(); dataLine = NULL; ++i; nextLine = ((i + 1) < nrLines ? ((TObjString *)(lines->At(i + 1)))->GetString().Data() : ""); - nextLine = Sanitize(nextLine); } } } else { AliError("Survey text file sintax error!"); lines->Delete(); + delete lines; lines = NULL; return kFALSE; } } lines->Delete(); + delete lines; lines = NULL; fIsValid = kTRUE; return kTRUE; } +//_____________________________________________________________________________ +void AliSurveyObj::Reset() { + // Resets the AliSurveyObj to a clean object. + // Used if the same object is filled more than once + + if (fDataPoints) { + fDataPoints->Delete(); + fDataPoints = 0; + } + fTitle = ""; + fDate = ""; + fDetector = ""; + fURL = "http://edms.cern.ch/"; + fReportNr = -1; + fVersion = -1; + fObs = ""; + fCoordSys = ""; + fUnits = ""; + fNrColumns = -1; + fColNames = ""; + fIsValid = kFALSE; + fDataPoints = new TObjArray(1); + fDataPoints->SetOwner(kTRUE); + return; +} +