#include <TextInFile.hpp>
Classes | |
class | ColumnInfo |
Public Member Functions | |
TextInFile (const SimulationItem *item, string filename, string description, bool resource=false) | |
~TextInFile () | |
void | addColumn (string description, string quantity=string(), string defaultUnit=string()) |
void | close () |
vector< Array > | readAllColumns () |
template<typename... Columns, typename = std::enable_if_t<sizeof...(Columns) != 0>> | |
void | readAllColumns (Columns &... columns) |
vector< Array > | readAllRows () |
bool | readNonLeaf (int &nx, int &ny, int &nz) |
bool | readRow (Array &values) |
template<typename... Values, typename = std::enable_if_t<CompileTimeUtils::isFloatArgList<Values...>()>> | |
bool | readRow (Values &... values) |
void | useColumns (string columns) |
Private Member Functions | |
size_t | indexForName (string name) const |
size_t | waveIndexForSpecificQuantity () const |
Static Private Member Functions | |
template<typename... Columns> | |
static void | assignColumns (size_t index, vector< Array > &result, Array &column, Columns &... columns) |
static void | assignColumns (size_t, vector< Array > &) |
template<typename... Values> | |
static void | assignValues (size_t index, const Array &result, double &value, Values &... values) |
static void | assignValues (size_t, const Array &) |
Private Attributes | |
vector< ColumnInfo > | _colv |
bool | _hasBinaryOpen |
bool | _hasFileInfo |
bool | _hasProgInfo |
bool | _hasTextOpen |
std::ifstream | _in |
bool | _isResource |
Log * | _log |
vector< size_t > | _logColIndices |
size_t | _numLogCols |
StoredColumns | _scol |
Units * | _units |
This class allows reading a table of floating point values from a column text file with support for unit conversions. The filename is specified in the constructor, and information about the columns expected in the file is specified by calling the addColumn() function for each column.
When reading a column text file, empty lines and lines starting with # are ignored, except for the unit specification header lines described below. Other lines must contain a predefined number of floating point values separated by whitespace (spaces or tabs). The number of expected values is determined for each input file under program control. It is an error for a line to contain fewer values than expected (or for any of the values to be improperly formatted). On the other hand, any additional information on a line beyond the last expected value is ignored.
It is recommended that the header of the input file includes column information in the format described below. For example, a two-column input file might have the following header:
# My personal SED written from Python # column 1: wavelength (A) # column 2: specific luminosity (W/Hz) # ... data ...
There must be a header line for each column with the following contents from left to right:
Extra whitespace is allowed between the various fields. The unit string must exactly match one of the unit strings supported by SKIRT for the expected quantity. The column info lines must occur in the same order as the data columns. Extra header lines are allowed between, before, and after the column info lines.
If there is no column information in the file (i.e. none of the header lines match the syntax decribed above), the default units provided by the program are used.
Reading large text files can be very slow. Therefore, in certain cases, this class supports the possibility to provide the input file in a much faster SKIRT-specific binary file format, i.e. the stored columns format described in the StoredColumns class. This file format has the following limitations:
If the input file provided to the TextInFile constructor has the .scol filename extension, the implementation automatically switches to reading the binary file format instead of the regular column text format. This is fully transparent to the caller of the TextInFile class.
TextInFile::TextInFile | ( | const SimulationItem * | item, |
string | filename, | ||
string | description, | ||
bool | resource = false |
||
) |
The constructor opens the specified file for reading; if the file can't be opened, a FatalError is thrown. The constructor takes several arguments: (1) item specifies a simulation item in the hierarchy of the caller (usually the caller itself) used to retrieve the input file path and an appropriate logger; (2) filename specifies the name of the file, including filename extension but excluding path and simulation prefix; (3) description describes the contents of the file for use in the log message issued after the file is successfully opened; (4) resource indicates whether the file is located in the resources directory (true) or in the regular user input file directory (false, the default value).
If the specified file has the .scol filename extension, the implementation automatically switches to reading the binary SKIRT column file format instead of the regular column text format. For more information, see the class header.
TextInFile::~TextInFile | ( | ) |
void TextInFile::addColumn | ( | string | description, |
string | quantity = string() , |
||
string | defaultUnit = string() |
||
) |
This function (virtually) adds a new column to the text file, characterized by the given description and unit information. The description argument is used only for logging purposes. The quantity argument specifies the physical quantity represented by the column. It must match one of the quantity strings supported by the Units system, or one of the special quantity strings recognized by this class (see below). The defaultUnit argument specifies the default unit string, which is used in case the input file does not contain column information.
In addition to the quantity strings supported by the Units system, this function supports the following special quantity strings.
The function looks for and, if present, reads the header information line corresponding to this column. The unit information from the header is stored with the information provided by the function arguments for later use.
void TextInFile::close | ( | ) |
This function closes the file if it was not already closed. It is best to call close() or allow the object to go out of scope before logging other messages or starting another significant chunk of work.
|
private |
This function returns the zero-based index of the column that has a file info description equal to the given name, or an error value if there is no such column or if there are multiple such columns.
vector< Array > TextInFile::readAllColumns | ( | ) |
This function reads all rows from a column text file (from the current position until the end of the file), transposes the data repesentation from rows into columns, and returns the resulting values as a vector of column arrays. For each row, this function behaves just like readRow(Array&).
|
inline |
This function reads all rows from a column text file (from the current position until the end of the file), transposes the data repesentation from rows into columns, and stores the resulting column arrays in the variables passed to the function by reference. For each row, this function behaves just like readRow(Array&).
vector< Array > TextInFile::readAllRows | ( | ) |
This function reads all rows from a column text file (from the current position until the end of the file), and returns the resulting values as a vector of row arrays. For each row, this function behaves just like readRow(Array&).
bool TextInFile::readNonLeaf | ( | int & | nx, |
int & | ny, | ||
int & | nz | ||
) |
This is a specialty function intended for use by the AdaptiveMeshSnapshot class when importing an adaptive mesh text column file. The function attempts to read a line containing a nonleaf node specification. Such a line starts with an exclamation mark, which must be followed by three integers (one subdivision specifier for each dimension).
If the next line (after skipping comments and empty lines) starts with an exclamation mark, the function processes it as a nonleaf node specification. If this is successful, the function stores the parsed specifiers in the arguments and returns true. If the line cannot be parsed, a fatal error is thrown.
If the next line (after skipping comments and empty lines) does not start with an exclamation mark, the contents of the function arguments is undefined and the function returns false. In this case, the function has not consumed any information other than comments and white space. The file cursor is left just before the next regular line (i.e. a line not starting with an exclamation mark), or at the end of the file.
bool TextInFile::readRow | ( | Array & | values | ) |
This function reads the next row from a column text file and stores the resulting values in the array passed to the function by reference. The function first skips empty lines and lines starting with a hash character, and then reads a single text line containing data values separated by white space.
The number of expected values corresponds to the number of columns in the file, which is determined by repeated calls to the addColumn() function. If the data line contains fewer values than expected, or if any of the values is improperly formatted for a floating point number, the function throws a FatalError (the size and contents of the values array are undefined). Any additional information on the line beyond the last expected value is ignored.
If a row was successfully read, the input values are converted from the input units (as specified in the file header or using the default given in the addColumn() function) to SKIRT-internal units. Finally, the values array is set to the appropriate length, the converted input values are stored into it in column order, and the function returns true.
If the end of the file is reached before a row can be read, the function returns false and the size and contents of the values array are undefined.
|
inline |
This variadic template function reads the next row from a column text file and stores the resulting values in the variables passed to the function by reference. For example:
double a,b,c,d; bool success = in.readRow(a,b,c,d); // reads a row from a file with 4 columns
This function behaves just like the readRow(Array&) version. The number of arguments must match the number of columns in the file.
void TextInFile::useColumns | ( | string | columns | ) |
This function specifies a mapping (defined by the columns argument, as described below) between the "physical" columns in the file (defined by the column information in the file header) and the "logical" columns requested by the program (defined by repeated calls to the addColumn() function). This function can be called with a non-empty columns string at most once for each file, and such invocation should occur before the first invocation of the addColumn() function. Calling this function with an empty columns string is equivalent to not calling it at all.
If the columns string is non-empty, it is interpreted as a comma-separated sequence of logical column names. Within each column name, consecutive white space characters are replaced by a single space, and white space at the start and at the end is removed. The following rules then apply:
These rules define a mapping between the physical file column ordering and the logical column ordering defined by the columns string. Once this mapping has been established, the program only sees the logical ordering. In other words, the subsequent calls to the addColumn() function are matched to the corresponding logical columns, and the readXxx() functions retrieve logical columns only.
|
private |
This function returns the index of the first column that is described as "wavelength", or the error value if there is no such column.