/* * ScanStream.cpp * * Created on: Nov 17, 2016 * Author: Hovanes Egiyan */ #include #include #include #include "boost/algorithm/string/classification.hpp" #include "ScanStream.hh" #include "Scan.hh" #include "ScanFile.hh" ClassImp(ScanStream) using namespace std; ScanStream::ScanStream( ScanFile* inFile ) : TObject(), scanFile( inFile ), scanNumber(-1), scanRank(0), nPoints(0), nDetectors(0), nPositioners(0), nTriggers(0), scanName("None"), scanTime("None"), nDetectorsRead(0), nPositionersRead(0) { try { initAttributes(); readMDAStream(); } catch (const runtime_error & e) { string errMsg = e.what(); cerr << errMsg << endl; throw e; } } ScanStream::~ScanStream() { // Loop through the detector pointer vector and delete the existing detectors for ( unsigned iDet = 0; iDet < scanDetector.size(); iDet++ ) { if( scanDetector[iDet] != 0 ) delete scanDetector[iDet]; } } // Reads the MDA stream to define a scan. If the stream is in the middle of a file // it is still OK since it means that it is jsut a subscan. void ScanStream::readMDAStream() { string sLine; cout << "Entered readMDAStream" << endl; while (getline( (*(scanFile->getFileStream())), sLine)) { // cout << "Line Content is :" << sLine << endl; // Define a stream from the current line read from the file istringstream strmLine; strmLine.str(sLine); // // Check if the line defines an attribute bool attribIsFound = checkForAttributes(strmLine); if (attribIsFound) { printAttributes(); } // Check if the line defines a detector int detSetNumber = checkForDetectors(strmLine); if (detSetNumber > 0) { ScanDetector* newDetectorPtr = 0; // Read the lines from the stream and define the detector try { // This call will define a new detector object and also will // advance the current location in the stream newDetectorPtr = new ScanDetector( (*(scanFile->getFileStream()) ), this); } catch (const runtime_error & e) { string errMsg = e.what(); cerr << errMsg << endl; throw e; } // If reached here push the pointer into the detector vector scanDetector[detSetNumber] = newDetectorPtr; cout << "Found and built detector <" << newDetectorPtr->getName() << "> : " << newDetectorPtr->getDesciption() << endl; } // Check if the line define a positioner int posSetNumber = checkForPositioners(strmLine); if ( posSetNumber > 0 ) { ScanPositioner* newPositionerPtr = 0; // Read the lines from the stream and define the positioner try { // This call will define a new positioner object and also will // advance the current location in the stream newPositionerPtr = new ScanPositioner((*(scanFile->getFileStream()))); } catch (const runtime_error & e) { string errMsg = e.what(); cerr << errMsg << endl; throw e; } // If reached here push the pointer into the detector vector scanPositioner[posSetNumber] = newPositionerPtr; cout << "Found and built positioner <" << newPositionerPtr->getName() << "> : " << newPositionerPtr->getDesciption() << endl; } // Check if the line defines Positioner Data int positionerDataSetNumber = checkForPositionerData(strmLine); if ( positionerDataSetNumber > 0 ) { // Read the lines from the stream and define the data try { // This call will define a new data object and also will // advance the current location in the stream scanPositioner[positionerDataSetNumber]->readData( (*(scanFile->getFileStream())) ); // scanPositioner[positionerDataSetNumber]->printData(); nPositionersRead++; } catch (const runtime_error & e) { string errMsg = e.what(); cerr << errMsg << endl; throw e; } cout << "Created positioner data set " << positionerDataSetNumber << endl; if( scanStreamReadComplete() ) { cout << "Reached expected component number, returning" << endl; return; } } // Check if the line defines Detector Data int detectorDataSetNumber = checkForDetectorData(strmLine); if ( detectorDataSetNumber > 0 ) { // Read the lines from the stream and define the data try { // This call will define a new data object and also will // advance the current location in the stream cout << "Input file stream pointer is " << scanFile->getFileStream() << endl; cout << "Detector set number found is " << detectorDataSetNumber << endl; scanDetector[detectorDataSetNumber]->readData( (*(scanFile->getFileStream())) ); nDetectorsRead++; // scanDetector[detectorDataSetNumber]->printData(); } catch (const runtime_error & e) { string errMsg = e.what(); cerr << errMsg << endl; throw e; } cout << "Created detector data set " << detectorDataSetNumber << endl; if( scanStreamReadComplete() ) { cout << "Reached expected component number, returning" << endl; return; } } int subScanNumber = checkForSubscan(strmLine); if( subScanNumber > 0 ) { cout << "Will deal with subscan #" << subScanNumber << endl; Scan* newScanPtr = 0; try { // This call will define a new data object and also will // advance the current location in the stream newScanPtr = new Scan( scanFile, subScanNumber ); cout << "Created subscan #" << subScanNumber << endl; subScan[subScanNumber] = newScanPtr; cout << "Subscan map size should have incremented to " << subScan.size() << endl; } catch (const runtime_error & e) { string errMsg = e.what(); cerr << errMsg << endl; throw e; } if( scanStreamReadComplete() ) { cout << "Reached expected component number, returning" << endl; return; } } // If we got to comment section we simply stop looping for the rest of the file if( checkForComments(strmLine) ) { // cout << "Reached comments, will return" << endl; // return; } // Increment the line number // iLine++; } cout << "Reached end of readMDAStream, nothing strange" << endl; return; } // Set the references for the attributes to the data members of the class. // The maps only contain information about the scan attributes that will // be read from the MDA file. For instance, the file name is not going to be // present in these maps. void ScanStream::initAttributes() { // Pointers to data members that are expected to be found in the MDA data file scanIntAttribute["scanNumber"] = &scanNumber ; scanIntAttribute["scanRank"] = &scanRank ; scanIntAttribute["nPoints"] = &nPoints ; scanIntAttribute["nDetectors"] = &nDetectors ; scanIntAttribute["nPositioners"] = &nPositioners ; scanIntAttribute["nTriggers"] = &nTriggers ; scanStringAttribute["scanName"] = &scanName ; scanStringAttribute["scanTime"] = &scanTime ; // scanStringAttribute["fileName"] = &fileName ; // Strings to look for in the MDA file scanAttributeToken["scanNumber"] = "Scan number" ; scanAttributeToken["scanRank"] = "This scan's rank" ; scanAttributeToken["nPoints"] = "Last completed point" ; scanAttributeToken["nDetectors"] = "Number of detectors" ; scanAttributeToken["nPositioners"] = "Number of positioners" ; scanAttributeToken["nTriggers"] = "Number of triggers" ; scanAttributeToken["scanName"] = "Scan name" ; scanAttributeToken["scanTime"] = "Scan time" ; // scanAttributeToken["fileName"] = "No such String Exist" ; return; } bool ScanStream::scanStreamReadComplete() { cout << "Checking: scanRank is " << scanRank << " nDetectors is " << nDetectors << " found " << nDetectorsRead << " detectors " << " nPositioners is " << nPositioners << " found " << nPositionersRead << " positioners " << endl; if ( (scanRank == 1 && ( nDetectorsRead< nDetectors || nPositionersRead < nPositioners) ) || scanRank == 2 ) { return false; } else { return true; } } // Print attributes that can be read from the file. These are the ones that are stored in a map. void ScanStream::printAttributes() { for( map::iterator it = scanIntAttribute.begin(); it != scanIntAttribute.end(); it ++ ) { cout << " " << it->first << " : " << *(it->second) << " , " ; } cout << endl; for( map::iterator it = scanStringAttribute.begin(); it != scanStringAttribute.end(); it ++ ) { cout << " " << it->first << " : " << *(it->second) << " , " ; } cout << endl; return; } // Method that looks into a line that is passed in form of a stream // and tries to see if the lines defines an attribute of a scan. Attribute of // a scan is separate from a detector definition or positioner definition. // Returns 1 if the current line defines a scan attribute and 0 if it does not // define any of the scan attributes. bool ScanStream::checkForAttributes(istringstream& strmLine) { bool result = false; // boolean variable initialized as false. vector stringVector; string sLine = strmLine.str(); // Split the string using "=" as a delimiter boost::split(stringVector, sLine, boost::algorithm::is_any_of("=")); // Loop through all defined signature of an attribute in a MDA file and check if // first token in front of the line matches any of them. for (map::iterator it = scanAttributeToken.begin(); it != scanAttributeToken.end(); it++) { string attribName = it->first; string attribToken = it->second; // Check if the first token matches the current attribute signature in the file if ( stringVector[0].find( attribToken ) != std::string::npos ) { // See if it is an integer type attribute if ( scanIntAttribute.count(attribName) > 0) { if (stringVector.size() > 2) { // If there are more than one "=" signs in the lines that has amatching // token print en error message. cout << "ERROR in ScanFile::checkForAttributes: More than two ScanFile attributes defined" << endl; } // Convert the string values to integer value to assign to the integer attribute stringstream ssAttributes; ssAttributes << stringVector[1]; int attribValue; ssAttributes >> attribValue; *scanIntAttribute[attribName] = attribValue; result = true; } // See if it is a string type attribute if (scanStringAttribute.count(attribName) > 0) { if (stringVector.size() > 2) { // If there are more than one "=" signs in the lines that has a matching // token print en error message. cout << "ERROR in ScanFile::checkForAttributes: More than two ScanFile attributes defined" << endl; } *scanStringAttribute[attribName] = stringVector[1]; result = true; } } } return result; } int ScanStream::checkForDetectors(istringstream& strmLine) { int detSetNumber = 0; string sLine = strmLine.str(); // Check if the first token in front of the "#" sign is declaration of a detector if( sLine.find( "Detector Data Set #" ) != string::npos ) { vector stringVector; // Split the string using "=" as a delimiter boost::algorithm::split(stringVector, sLine, boost::algorithm::is_any_of("#")); stringstream ssNumber; ssNumber << stringVector[1]; ssNumber >> detSetNumber; } return detSetNumber; } int ScanStream::checkForPositioners(istringstream& strmLine) { int posSetNumber = 0; string sLine = strmLine.str(); // Check if the first token in front of the "#" sign is declaration of a detector if( sLine.find( "Positioner Data Set #" ) != string::npos ) { vector stringVector; // Split the string using "=" as a delimiter boost::split(stringVector, sLine, boost::algorithm::is_any_of("#")); stringstream ssNumber; ssNumber << stringVector[1]; ssNumber >> posSetNumber; } return posSetNumber; } // Method to check if the current line defines a subscan and returns the // subscan number. int ScanStream::checkForSubscan( istringstream& strmLine ) { int subScanNumber = 0; string sLine = strmLine.str(); // Check if the first token in front of the "#" sign is declaration of a detector if( sLine.find( "Subscan #" ) != string::npos ) { vector stringVector; // Split the string using "=" as a delimiter boost::split(stringVector, sLine, boost::algorithm::is_any_of("#")); stringstream ssNumber; ssNumber << stringVector[1]; ssNumber >> subScanNumber; } return subScanNumber; } bool ScanStream::checkForComments(istringstream& strmLine) { string sLine = strmLine.str(); if( sLine.find( "Extra PV Offset" ) != string::npos ) { return true; } return false; } int ScanStream::checkForDetectorData(istringstream& strmLine) { int detNumber = 0; string sLine = strmLine.str(); // Check if the line is consistent with declaration of detector data if( ( sLine.find( "Detector #" ) != string::npos ) && ( sLine.find( "data:" ) != string::npos ) ) { size_t poundLocation = sLine.find("#"); // Get pound location string afterPoundStr = sLine.substr( poundLocation+1 ); // Substring after pound sign vector stringVector; // Split the string using " " as a delimiter boost::split( stringVector, afterPoundStr, boost::is_any_of(" ") ); // Convert the string values to integer value to assign to the integer attribute stringstream ssNumber; ssNumber << stringVector[0]; ssNumber >> detNumber; } return detNumber; } int ScanStream::checkForPositionerData(istringstream& strmLine) { int posNumber = 0; string sLine = strmLine.str(); // Check if the line is consistent with declaration of detector data if( ( sLine.find( "Positioner #1" ) != string::npos ) && ( sLine.find( "data:" ) != string::npos ) ) { size_t poundLocation = sLine.find("#"); // Get pound location string afterPoundStr = sLine.substr( poundLocation+1 ); // Substring after pound sign vector stringVector; // Split the string using " " as a delimiter boost::split( stringVector, afterPoundStr, boost::is_any_of(" ") ); // Convert the string values to integer value to assign to the integer attribute stringstream ssNumber; ssNumber << stringVector[0]; ssNumber >> posNumber; } return posNumber; }