#include #include #include #include #include #include #include "TFile.h" #include "TH2D.h" using namespace std; class GoniPointData { public: double dGoniXPosition; //in mm double dGoniYPosition; //in mm deque dScalarData; //corresponds to GoniScanData::dScalarNames }; class GoniScanData { public: GoniScanData(void); //BINNING INFO double dMinScanX; double dMaxScanX; double dScanStepSizeX; double dMinScanY; double dMaxScanY; double dScanStepSizeY; //INPUT INFO string dFirstInputFileName; //e.g. for goniXY_scan_0052_#.asc, this should be: goniXY_scan_0052_ //DATA INFO bool dXIsListedFirstFlag; deque dScalarNames; //corresponds to GoniPointData::dScalarData deque dGoniPointData; }; GoniScanData::GoniScanData(void) : dMinScanX(9.9E9), dMaxScanX(-9.9E9), dScanStepSizeX(-1.0), dMinScanY(9.9E9), dMaxScanY(-9.9E9), dScanStepSizeY(-1.0) {} string Format_Name(string locString); void Plot_Data(GoniScanData& locGoniScanData); void Extract_Binning(GoniScanData& locGoniScanData); bool Extract_ScalarName(string locLine, string& locScalarName); void Load_ScanData(GoniScanData& locGoniScanData); bool Load_FileData(string locInputFileName, bool locIsFirstFileFlag, GoniScanData& locGoniScanData); int main(int argc, char** argv) { //USAGE cout << "USAGE: Call with one argument: The path/name to any of the ascii files made from mda2ascii (e.g. goniXY_scan_0052_1.asc)." << endl; cout << endl; if(argc != 2) { cout << "INCORRECT NUMBER OF ARGUMENTS! EXITING." << endl; return 666; } //READ INPUTS GoniScanData locGoniScanData; string locFirstInputFileFullPath = argv[1]; //e.g. for goniXY_scan_0052_1.asc locGoniScanData.dFirstInputFileName = locFirstInputFileFullPath; //READ DATA Load_ScanData(locGoniScanData); //OPEN OUTPUT ROOT FILE size_t locStringIndex = locFirstInputFileFullPath.find_last_of("/"); string locFirstInputFileName = (locStringIndex != string::npos) ? locFirstInputFileFullPath.substr(locStringIndex + 1) : locFirstInputFileFullPath; string locOutputFileName = locFirstInputFileName.substr(0, locFirstInputFileName.size() - 5) + string("plots.root"); TFile* locOutputFile = new TFile(locOutputFileName.c_str(), "RECREATE"); //PLOT DATA FOR EACH SCALAR Extract_Binning(locGoniScanData); Plot_Data(locGoniScanData); //WRITE-TO AND CLOSE OUTPUT ROOT FILE locOutputFile->Write(); locOutputFile->Close(); delete locOutputFile; return 0; } void Load_ScanData(GoniScanData& locGoniScanData) { //build file names unsigned int locFileNumber = 1; while(true) { ostringstream locFileNumberStream; locFileNumberStream << locFileNumber; string locScanFileName = locGoniScanData.dFirstInputFileName; if(locFileNumber < 10) locScanFileName = locScanFileName.substr(0, locScanFileName.size() - 5); else locScanFileName = locScanFileName.substr(0, locScanFileName.size() - 6); locScanFileName += locFileNumberStream.str() + string(".asc"); bool locIsFirstFileFlag = (locFileNumber == 1); if(!Load_FileData(locScanFileName, locIsFirstFileFlag, locGoniScanData)) break; ++locFileNumber; } } bool Load_FileData(string locInputFileName, bool locIsFirstFileFlag, GoniScanData& locGoniScanData) { //open input file cout << "Attempting to open file: " << locInputFileName << endl; ifstream locInputFileStream(locInputFileName.c_str()); if(!locInputFileStream.is_open()) { cout << "File does not exist. Finished reading data." << endl; return false; //not valid } cout << "Opened input file: " << locInputFileName << endl; //read header info to figure out file parameters string locLine; if(locIsFirstFileFlag) { //skip until you find: # Column Descriptions:" while(std::getline(locInputFileStream, locLine)) { if(locLine.find("# Column Descriptions", 0) != string::npos) break; } if(!locInputFileStream) { cout << "ERROR: IMPROPERLY FORMATTED HEADER." << endl; return false; } //see if x or y is scanned in the outer loop if(!std::getline(locInputFileStream, locLine)) { cout << "ERROR: IMPROPERLY FORMATTED HEADER." << endl; return false; } //skip until you find: "# Column Descriptions:" while(std::getline(locInputFileStream, locLine)) { if(locLine.find("# Column Descriptions", 0) != string::npos) break; } if(!locInputFileStream) { cout << "ERROR: IMPROPERLY FORMATTED HEADER." << endl; return false; } //skip until you find: "1-D Detector:" while(std::getline(locInputFileStream, locLine)) { if(locLine.find("1-D Detector", 0) != string::npos) break; } if(!locInputFileStream) { cout << "ERROR: IMPROPERLY FORMATTED HEADER." << endl; return false; } //see if x or y is listed first, then skip the next line (other y/x) locGoniScanData.dXIsListedFirstFlag = (locLine.find("X.RBV", 0) != string::npos); std::getline(locInputFileStream, locLine); //for the following lines that have "1-D Detector:" save the scalar names while(std::getline(locInputFileStream, locLine)) { if(locLine.find("1-D Detector", 0) == string::npos) break; string locScalarName = ""; if(!Extract_ScalarName(locLine, locScalarName)) { cout << "ERROR: IMPROPERLY FORMATTED HEADER." << endl; return false; } locGoniScanData.dScalarNames.push_back(locScalarName); } if(!locInputFileStream) { cout << "ERROR: IMPROPERLY FORMATTED HEADER." << endl; return false; } cout << "Scalar names: "; for(size_t loc_i = 0; loc_i < locGoniScanData.dScalarNames.size(); ++loc_i) { if(loc_i != 0) cout << ", "; cout << locGoniScanData.dScalarNames[loc_i]; } cout << endl; cout << "Header data successfully interpreted, " << locGoniScanData.dScalarNames.size() << " scalars found." << endl; } //skip until you find: "# 1-D Scan Values" while(std::getline(locInputFileStream, locLine)) { if(locLine.find("# 1-D Scan Values", 0) != string::npos) break; } if(!locInputFileStream) { cout << "ERROR: IMPROPERLY FORMATTED HEADER." << endl; return false; } //read in data size_t locPreReadRecords = locGoniScanData.dGoniPointData.size(); cout << "Reading in data." << endl; while(std::getline(locInputFileStream, locLine)) { istringstream locLineStream(locLine); double locValue; //(skip first and second columns) (id, set value) if(!(locLineStream >> locValue >> locValue)) { cout << "ERROR: IMPROPERLY FORMATTED DATA." << endl; return false; } //read in the x & y position GoniPointData locGoniPointData; if(locGoniScanData.dXIsListedFirstFlag) locLineStream >> locGoniPointData.dGoniXPosition >> locGoniPointData.dGoniYPosition; else locLineStream >> locGoniPointData.dGoniYPosition >> locGoniPointData.dGoniXPosition; if(!locLineStream) { cout << "ERROR: IMPROPERLY FORMATTED DATA." << endl; return false; } //read in the scalar data locGoniPointData.dScalarData.resize(locGoniScanData.dScalarNames.size()); for(size_t loc_i = 0; loc_i < locGoniScanData.dScalarNames.size(); ++loc_i) { if(!(locLineStream >> locValue)) locValue = -1.0/0.0; //NaN locGoniPointData.dScalarData[loc_i] = locValue; } cout << "goni x/y, scalars = " << locGoniPointData.dGoniXPosition << ", " << locGoniPointData.dGoniYPosition; for(size_t loc_i = 0; loc_i < locGoniScanData.dScalarNames.size(); ++loc_i) cout << ", " << locGoniPointData.dScalarData[loc_i]; cout << endl; //save the scalar data locGoniScanData.dGoniPointData.push_back(locGoniPointData); } size_t locNumThisFileRecords = locGoniScanData.dGoniPointData.size() - locPreReadRecords; cout << "Read " << locNumThisFileRecords << " records from this file, " << locGoniScanData.dGoniPointData.size() << " total." << endl; return true; } bool Extract_ScalarName(string locLine, string& locScalarName) { size_t locStringIndex = locLine.find("]", 0); if(locStringIndex == string::npos) return false; size_t locFirstNameIndex = locLine.find_first_not_of(" ", locStringIndex + 1); if(locFirstNameIndex == string::npos) return false; size_t locCommaIndex = locLine.find_first_of(",", locFirstNameIndex); if(locCommaIndex == string::npos) return false; locScalarName = locLine.substr(locFirstNameIndex, locCommaIndex - locFirstNameIndex); return true; } void Extract_Binning(GoniScanData& locGoniScanData) { for(size_t loc_i = 0; loc_i < locGoniScanData.dGoniPointData.size(); ++loc_i) { GoniPointData& locGoniPointData = locGoniScanData.dGoniPointData[loc_i]; if((locGoniScanData.dScanStepSizeX < 0.0) && (locGoniScanData.dMinScanX < 9.9E9)) { //not set yet, but min is set (something to this compare against) //"this" and min values will either be identical or adjacent double locStepSize = fabs(locGoniPointData.dGoniXPosition - locGoniScanData.dMinScanX); if(locStepSize > 0.0) //not the same locGoniScanData.dScanStepSizeX = locStepSize; } if((locGoniScanData.dScanStepSizeY < 0.0) && (locGoniScanData.dMinScanY < 9.9E9)) { //not set yet, but min is set (something to this compare against) //"this" and min values will either be identical or adjacent double locStepSize = fabs(locGoniPointData.dGoniYPosition - locGoniScanData.dMinScanY); if(locStepSize > 0.0) //not the same locGoniScanData.dScanStepSizeY = locStepSize; } if(locGoniPointData.dGoniXPosition < locGoniScanData.dMinScanX) locGoniScanData.dMinScanX = locGoniPointData.dGoniXPosition; if(locGoniPointData.dGoniXPosition > locGoniScanData.dMaxScanX) locGoniScanData.dMaxScanX = locGoniPointData.dGoniXPosition; if(locGoniPointData.dGoniYPosition < locGoniScanData.dMinScanY) locGoniScanData.dMinScanY = locGoniPointData.dGoniYPosition; if(locGoniPointData.dGoniYPosition > locGoniScanData.dMaxScanY) locGoniScanData.dMaxScanY = locGoniPointData.dGoniYPosition; } cout << "X: min/max/step = " << locGoniScanData.dMinScanX << ", " << locGoniScanData.dMaxScanX << ", " << locGoniScanData.dScanStepSizeX << endl; cout << "Y: min/max/step = " << locGoniScanData.dMinScanY << ", " << locGoniScanData.dMaxScanY << ", " << locGoniScanData.dScanStepSizeY << endl; } void Plot_Data(GoniScanData& locGoniScanData) { //# bins: e.g.: if scan at 0.0, 0.5, 1.0 there are 3!! bins int locNumBinsX = int((locGoniScanData.dMaxScanX - locGoniScanData.dMinScanX)/locGoniScanData.dScanStepSizeX + 0.00001) + 1; double locMinXEdge = locGoniScanData.dMinScanX - locGoniScanData.dScanStepSizeX/2.0; double locMaxXEdge = locGoniScanData.dMaxScanX + locGoniScanData.dScanStepSizeX/2.0; int locNumBinsY = int((locGoniScanData.dMaxScanY - locGoniScanData.dMinScanY)/locGoniScanData.dScanStepSizeY + 0.00001) + 1; double locMinYEdge = locGoniScanData.dMinScanY - locGoniScanData.dScanStepSizeY/2.0; double locMaxYEdge = locGoniScanData.dMaxScanY + locGoniScanData.dScanStepSizeY/2.0; //loop over scalars for(size_t loc_i = 0; loc_i < locGoniScanData.dScalarNames.size(); ++loc_i) { string locHistName = Format_Name(locGoniScanData.dScalarNames[loc_i]); string locHistTitle = locGoniScanData.dScalarNames[loc_i] + string(";Goniometer X (mm);Goniometer Y (mm)"); TH2D* locHist = new TH2D(locHistName.c_str(), locHistTitle.c_str(), locNumBinsX, locMinXEdge, locMaxXEdge, locNumBinsY, locMinYEdge, locMaxYEdge); //loop over data points for(size_t loc_j = 0; loc_j < locGoniScanData.dGoniPointData.size(); ++loc_j) { GoniPointData& locGoniPointData = locGoniScanData.dGoniPointData[loc_j]; int locBin = locHist->FindBin(locGoniPointData.dGoniXPosition, locGoniPointData.dGoniYPosition); double locScalar = locGoniPointData.dScalarData[loc_i]; locHist->SetBinContent(locBin, locScalar); } } } string Format_Name(string locString) { //replace all ":" with "_" size_t locStringIndex = locString.find(":", 0); while(locStringIndex != string::npos) { locString.replace(locStringIndex, 1, "_"); ++locStringIndex; locStringIndex = locString.find(":", locStringIndex); } //replace all "." with "_" locStringIndex = locString.find(".", 0); while(locStringIndex != string::npos) { locString.replace(locStringIndex, 1, "_"); ++locStringIndex; locStringIndex = locString.find(".", locStringIndex); } return locString; }