gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
asciireader.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
19 
22 #include "gambit/Logs/logger.hpp"
23 
24 namespace Gambit {
25  namespace Printers {
26 
28  uint safe_col_lookup(const std::string& key, const std::map<std::string,uint>& colmap, std::string fname)
29  {
30  auto it = colmap.find(key);
31  if(it==colmap.end())
32  {
33  std::ostringstream err;
34  err << "Error! asciiReader could not locate the required entry '"<<key<<"' in the info file '"<<fname<<"'. Please check that the supplied filename is a valid 'info' file produced by asciiPrinter in a previous scan." << std::endl;
35  printer_error().raise(LOCAL_INFO,err.str());
36  }
37  return it->second;
38  }
39 
41 
44  : infoFile_name( options.getValue<std::string>("info_filename") )
45  , dataFile_name( options.getValue<std::string>("data_filename") )
46  , column_map( get_column_info(infoFile_name) )
47  , col_rank( safe_col_lookup("MPIrank", column_map, infoFile_name) )
48  , col_ptID( safe_col_lookup("pointID", column_map, infoFile_name) )
49  , dataset_length(0)
50  , current_row(0)
51  , current_point(0,0)
52  , current_line("")
53  {
54  logger() << LogTags::info << "asciiReader: Constructing 'asciiReader' for performing retrieval from previous output. File to be accessed is:"<<std::endl;
55  logger() << " data file: " << dataFile_name << std::endl;
56  logger() << " info file: " << infoFile_name << std::endl;
57  logger() << EOM;
58 
60  dataFile.open(dataFile_name);
61 
62  if( dataFile.fail() )
63  {
64  std::ostringstream err;
65  err << "Error! asciiReader failed to open 'data' file '"<<dataFile_name<<"' for reading past scan output. OS message was: "<<strerror(errno);
66  printer_error().raise(LOCAL_INFO,err.str());
67  }
68 
72  if(eoi())
73  {
74  std::ostringstream err;
75  err << "Error! asciiReader reached end of input file '"<<dataFile_name<<"' immediately (file seems to be empty?). Please check the path specified in the YAML config file for this run." << std::endl;
76  printer_error().raise(LOCAL_INFO,err.str());
77  }
78 
79  while(not eoi())
80  {
83  }
84  // Note, there is an extra iteration here (one past the end), so the length is indeed the actual length (since we started counting at zero), not the index of the last entry.
85  reset();
86  }
87 
90  {
91  return dataset_length;
92  }
93 
94  // Get a linear index which corresponds to the current rank/ptID pair in the iterative sense
96  {
97  return current_row;
98  }
99 
102  {
103  dataFile.close();
104  dataFile.open(dataFile_name);
105 
106  if( dataFile.fail() )
107  {
108  std::ostringstream err;
109  err << "Error! asciiReader failed to re-open 'data' file '"<<dataFile_name<<"' for reading previous output while resetting read-head position. OS message was: "<<strerror(errno);
110  printer_error().raise(LOCAL_INFO,err.str());
111  }
112 
114  current_row = 0;
115  }
116 
117  // Get current rank/ptID pair in data file
118  // Make sure get_next_point has been called first! Otherwise we may not have a current point to get
120  {
121  return current_point;
122  }
123 
126  {
127  next_row();
128  // Point will get returned, but check eoi() before using it! If eoi() then we didn't actually get a new point, this should still just be the previous point.
129  return get_current_point();
130  }
131 
133  bool asciiReader::asciiReader::eoi()
134  {
135  //bool tmp = !dataFile;
136  //std::cout << "eoi()? " << tmp << std::endl;
137  //if(!dataFile) { std::cout << "At end of file!" << std::endl; }
138  return !dataFile;
139  }
140 
141 
142 
144  std::map<std::string,uint> asciiReader::get_column_info(const std::string& info_filename)
145  {
146  std::map<std::string,uint> column_map;
147 
148  std::ifstream infoFile;
149  infoFile.open(info_filename);
150 
151  if ( infoFile.fail() )
152  {
153  std::ostringstream err;
154  err << "Error! asciiReader failed to open 'info' file '"<<info_filename<<"' for reading column metadata. OS message was: "<< strerror(errno);
155  printer_error().raise(LOCAL_INFO,err.str());
156  }
157 
163  std::string line;
164  while(std::getline(infoFile, line)){
165  std::string garbage;
166  std::string description;
167  int col_index;
168  std::istringstream iss(line);
169  iss >> garbage; // First column is the just the word 'Column'
170  iss >> col_index; // Column index (I think the trailing colon will get ignored, so this is ok)
171  iss >> garbage; // The colon
172  iss >> std::ws; // Consume whitespace
173  getline(iss, description); // Put rest of line into the 'description' string.
174  column_map[description] = col_index-1; // convert to zero-indexed format
176  //std::cout << " From '"<<line<<"' extracted description '"<<description<<"' and index '"<<col_index-1<<"'"<<std::endl;
177  }
178  infoFile.close();
179 
180  return column_map;
181  }
182 
183  // Advance the read-head by one row
185  {
186  if(eoi())
187  {
188  std::ostringstream err;
189  err << "Error! asciiReader attempted to iterate past the end of the wrapped output file ("<<dataFile_name<<")! When iterating through output please check for the end-of-iteration via 'eoi()' before calling 'get_next_point()'.";
190  printer_error().raise(LOCAL_INFO,err.str());
191  }
192 
193  // Get new line data
194  std::getline(dataFile, current_line);
195  if(!eoi())
196  {
197  // Process line and find the MPIrank and pointID entries
198  std::istringstream iss(current_line);
199  unsigned int i=0;
200  std::string garbage; // can't use double, some entries might be 'none'
201  uint MPIrank = 0;
202  ulong pointID = 0;
203  double tmp; // Seem to need to convert to double first due to exponential notation
204  bool got_MPIrank(false);
205  bool got_pointID(false);
206 
207  while(i<=col_rank or i<=col_ptID)
208  {
209  if (i==col_rank){ iss >> tmp; MPIrank=(uint)(tmp+0.5); got_MPIrank=true; }
210  else if(i==col_ptID){ iss >> tmp; pointID=(ulong)(tmp+0.5); got_pointID=true; }
211  else { iss >> garbage; }
212  if(!iss)
213  {
214  std::ostringstream err;
215  err << "Error! asciiReader failed to read line '"<<current_row+1<<"', column '"<<i+1<<"' from the wrapped output file '"<<dataFile_name<<"'! The file may be corrupt.";
216  printer_error().raise(LOCAL_INFO,err.str());
217  }
218  i++;
219  }
220 
221  if(not got_MPIrank)
222  {
223  std::ostringstream err;
224  err << "Error! asciiReader failed to extract the MPIrank from line '"<<current_row+1<<"' of the wrapped output file '"<<dataFile_name<<"'!";
225  printer_error().raise(LOCAL_INFO,err.str());
226  }
227 
228  if(not got_pointID)
229  {
230  std::ostringstream err;
231  err << "Error! asciiReader failed to extract the pointID from line '"<<current_row+1<<"' of the wrapped output file '"<<dataFile_name<<"'!";
232  printer_error().raise(LOCAL_INFO,err.str());
233  }
234 
235  // Set new position data
236  current_point = PPIDpair(pointID,MPIrank);
237  current_row++;
238  // Before trying to access stuff from this row, check for end of file via eoi() function!
239  }
240  // Else do nothing, but make sure to check eoi() in other functions before trying to do stuff with this row!
241  }
242 
243 
245  void asciiReader::advance_to_point(const PPIDpair& target_point)
246  {
247  // Check if we are at the right place for the point already
248  if(current_point!=target_point)
249  {
250  //std::cout<<"Not at correct point! Move read head until we find it!"<<std::endl;//DEBUG
251  //std::cout<<" ("<<current_point.first<<", "<<current_point.second<<") ---> ("<<target_point.first<<","<<target_point.second<<")"<<std::endl;
252  // Need to search for the point
253  ulong start_pos = current_row; // Record starting position
254  bool begun_new_loop(false); // Flag to check if we have already looped past the end of the file once
255 
257  while(current_point!=target_point)
258  {
259  next_row();
260  if(eoi())
261  {
262  if(begun_new_loop)
263  {
264  // Already initiated new loop once; don't do it again!
265  std::ostringstream err;
266  err << "Error! asciiReader tried to initiate a second loop over output data while searching for a point in '"<<dataFile_name<<"'! This should never happen and indicates a bug in asciiPrinter, please file a bug report.";
267  printer_error().raise(LOCAL_INFO,err.str());
268  }
269 
272  reset();
273 
274  // Get first row data
275  next_row();
276  if(eoi()) // If it is still eoi() there is probably nothing in the file...
277  {
278  std::ostringstream err;
279  err << "Error! asciiReader could not find the requested MPIrank/pointID pair in the searched output data file '"<<dataFile_name<<"'! File appears to be empty or corrupted!";
280  printer_error().raise(LOCAL_INFO,err.str());
281  }
282  }
283 
284  // Check that we haven't been here already!
285  if(current_row==start_pos)
286  {
287  std::ostringstream err;
288  err << "Error! asciiReader could not find the requested MPIrank/pointID pair in the searched output data file '"<<dataFile_name<<"'! Please ensure that this point exists in the data file (e.g. by iterating through the full point list using 'get_next_point()')";
289  printer_error().raise(LOCAL_INFO,err.str());
290  }
291  }
292  }
293  //std::cout<<" Advanced to point: ("<<current_point.first<<", "<<current_point.second<<")"<<std::endl;
294  // Else Already at the right place! No need to do anything.
295  } // end function
296 
298  std::set<std::string> asciiReader::get_all_labels()
299  {
300  std::set<std::string> out;
301  for(auto it = column_map.begin(); it!=column_map.end(); ++it)
302  {
303  out.insert(it->first);
304  }
305  return out;
306  }
308 
309  }
310 }
virtual std::set< std::string > get_all_labels()
Get all output column labels.
EXPORT_SYMBOLS error & printer_error()
Printer errors.
void advance_to_point(const PPIDpair &target_point)
Advance the &#39;read head&#39; position for output retrieval until the requested rank/pointID entry is found...
const std::string dataFile_name
Definition: asciireader.hpp:64
virtual ulong get_current_index()
Definition: asciireader.cpp:95
#define LOCAL_INFO
Definition: local_info.hpp:34
STL namespace.
Ascii printer retriever class declaration This is a class accompanying the asciiPrinter which takes c...
const std::string infoFile_name
Definition: asciireader.hpp:57
Logging access header for GAMBIT.
void next_row()
Move &#39;read head&#39; forward to next row.
General small utility functions.
asciiReader(const Options &options)
General members of &#39;asciiReader&#39;.
Definition: asciireader.cpp:43
virtual PPIDpair get_current_point()
virtual void reset()
Base class virtual interface functions.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
unsigned long int ulong
const std::map< std::string, uint > column_map
Definition: asciireader.hpp:65
pointID / process number pair Used to identify a single parameter space point
TODO: see if we can use this one:
Definition: Analysis.hpp:33
A small wrapper object for &#39;options&#39; nodes.
virtual PPIDpair get_next_point()
Get next rank/ptID pair.
virtual ulong get_dataset_length()
Get total length of dataset.
Definition: asciireader.cpp:89
uint safe_col_lookup(const std::string &key, const std::map< std::string, uint > &colmap, std::string fname)
Helper function for map lookup.
Definition: asciireader.cpp:28
std::map< std::string, uint > get_column_info(const std::string &info_filename)
Get column descriptions from an info file.