nidas v1.2.3
|
A class for reading ASCII files containing a time series of calibration data. More...
#include <CalFile.h>
Public Member Functions | |
CalFile () | |
CalFile (const CalFile &) | |
Copy constructor. | |
CalFile & | operator= (const CalFile &) |
Assignment operator, like the copy constructor. | |
~CalFile () | |
Closes the file if necessary. | |
const std::string & | getFile () const |
void | setFile (const std::string &val) |
Set the base name of the file to be opened. | |
const std::string & | getPath () const |
Set the search path to find the file, and any included files: one or more directory paths separated by colons ':'. | |
void | setPath (const std::string &val) |
Set the search path to find the file, and any included files: one or more directory paths separated by colons ':'. | |
const std::string & | getCurrentFileName () const |
Return the full file path of the current file. | |
void | setName (const std::string &val) |
An instance of CalFile can have a name. | |
const std::string & | getName () const |
int | getLineNumber () const |
void | open () |
Open the file. | |
void | close () throw () |
Close file. | |
bool | eof () const |
Have we reached eof. | |
const std::string & | getTimeZone () const |
void | setTimeZone (const std::string &val) |
Set the timezone for the dates & times read from the file. | |
const std::string & | getDateTimeFormat () const |
void | setDateTimeFormat (const std::string &val) |
Set the format for reading the date & time from the file. | |
nidas::util::UTime | search (const nidas::util::UTime &tsearch) |
Search forward in a file, returning the time of the last record in the file with a time less than or equal to tsearch. | |
int | readCF (nidas::util::UTime &time, float *data, int ndata, std::vector< std::string > *fields=0) |
Read the time and data from the current record, and return the number of values read. | |
const std::vector< std::string > & | getCurrentFields (nidas::util::UTime *time=0) |
Return the time and fields of the current record, the one last read with readCF(). | |
nidas::util::UTime | getCurrentTime () |
float | getFloatField (int column, const std::vector< std::string > *fields=0) |
Convert the field at index column in the fields vector to a number, and return the number. | |
int | getFields (int begin, int end, float *data, const std::vector< std::string > *fields=0) |
Parse a range of columns from the fields vector as numbers and store them in the array data . | |
nidas::util::UTime | nextTime () throw () |
void | setDSMSensor (const DSMSensor *val) |
Set the DSMSensor associated with this CalFile. | |
const DSMSensor * | getDSMSensor () const |
void | fromDOMElement (const xercesc::DOMElement *node) |
virtual xercesc::DOMElement * | toDOMParent (xercesc::DOMElement *parent, bool complete) const |
Create a DOMElement and append it to the parent. | |
virtual xercesc::DOMElement * | toDOMElement (xercesc::DOMElement *node, bool complete) const |
Add my content into a DOMElement. | |
Static Public Member Functions | |
static std::vector< std::string > | getAllPaths () |
Return all the paths that have been set in all CalFile instances, in the order they were seen. | |
static const XMLCh * | getNamespaceURI () |
Protected Member Functions | |
nidas::util::UTime | parseTime () |
void | readLine () |
Read forward to next non-comment line in CalFile. | |
bool | parseTimeComments () |
Check the current line for special comments with timezone and datetime format settings. | |
int | parseInclude () |
If the current calfile record line is an include directive, parse the include filename, open it, and return 1. | |
void | openInclude (const std::string &name) |
int | readCFInclude (nidas::util::UTime &time, float *data, int ndata, std::vector< std::string > *fields_out) |
Internal version of readCF() which reads records from the current include file, if any. | |
Private Member Functions | |
nidas::util::UTime | readTime () |
Read lines, parsing special comment lines and skipping other comments or blank lines, until a record line is found. | |
int | readCFNoLock (nidas::util::UTime &time, float *data, int ndata, std::vector< std::string > *fields) |
Static Private Member Functions | |
static void | freeREs () |
static void | compileREs () |
Private Attributes | |
std::string | _name |
std::string | _fileName |
std::string | _path |
std::string | _currentFileName |
std::string | _timeZone |
bool | _utcZone |
std::string | _dateTimeFormat |
std::ifstream | _fin |
int | _curlineLength |
char * | _curline |
int | _curpos |
bool | _eofState |
int | _nline |
nidas::util::UTime | _nextTime |
nidas::util::UTime | _currentTime |
std::vector< std::string > | _currentFields |
nidas::util::UTime | _includeTime |
Time stamp of include "file" record. | |
nidas::util::UTime | _timeAfterInclude |
Time stamp of record after include "file". | |
nidas::util::UTime | _timeFromInclude |
Time stamp of last record in include file with time <= _includeTime. | |
CalFile * | _include |
const DSMSensor * | _sensor |
nidas::util::Mutex | _mutex |
Static Private Attributes | |
static const int | INITIAL_CURLINE_LENGTH = 128 |
static nidas::util::Mutex | _staticMutex |
static int | _reUsers = 0 |
static bool | _reCompiled = false |
static regex_t | _dateFormatPreg |
static regex_t | _timeZonePreg |
static regex_t | _includePreg |
static std::vector< std::string > | _allPaths |
static XMLCh * | namespaceURI = 0 |
A class for reading ASCII files containing a time series of calibration data.
CalFile supports reading files like the following:
Records are assumed to be time-ordered.
# example cal file # dateFormat = "%Y %b %d %H:%M:%S" # timeZone = "US/Mountain" # 2006 Sep 23 00:00:00 0.0 1.0 # Offset of 1.0 after Sep 29 01:13:00 2006 Sep 29 01:13:00 1.0 1.0 # use calibrations for ACME sensor SN#99 after Oct 1 2006 Oct 01 00:00:00 include "acme_sn99.dat"
As shown, comment lines begin with a '#'. There are two special comment lines, of the form 'dateFormat="blahblah"' and 'timeZone="blahblah". These specify the format of time in the calibration file. The dateFormat should contain date and time format descriptors as supported by the UNIX strftime function or as supported by the java.text.SimpleDateFormat class. Typically the dateFormat comment is found once in the file, before any data records.
If the dateFormat comment is not found in a file, and the dateTimeFormat attribute is not set on the instance of CalFile, then times must be in a format supported by nidas::util::UTime::parse.
field | example | UNIX | java |
---|---|---|---|
year | 2006 | %Y | YYYY |
month abrev | Sep | %b | MMM |
numeric month | 9 | %m | MM |
day of month | 14 | %d | dd |
day of year (1-366) | 257 | %j | DDD |
hour in day (00-23) | 13 | %H | HH |
minute(00-59) | 24 | %M | mm |
second(00-59) | 47 | %S | ss |
millisecond(000-999) | 447 | %3f<br>(UTime extension) | SSS |
Following the time fields in each record should be either numeric values or an "include" directive.
The numeric values should be space or tab separated values compatible with the usual floating point syntax, or the strings "na" or "nan" in either upper or lower case, representing not-a-number, or NaN. Since math operations using NaN result in a NaN, a calibration record containing a NaN value is a way to generate output values of NaN, indicating non-recoverable data.
An "include" directive causes another calibration file to be opened for input. The included file will be sequentially searched to set the input position to the last record with a time less than or equal to the time value of the "include directive. What this means is that the next readCF() will return data from the included file which is valid for the time of the include directive. An included file can also contain "include" directives. The include directive is useful when sensors are swapped during a data acquisition period. One can keep the sensor specific calibrations in separate files, and then create a CalFile which includes the sensor calibrations for the periods that a sensor was deployed. Example: <pre> # initially krypton hygrometer 1101 at this site 2006 Sep 23 00:00:00 include "krypton1101" # Replaced 1101 with 1393 on Oct 3. 2006 Oct 3 01:13:00 include "krypton1393" </pre> A typical usage of a CalFile is as follows: <pre> CalFile calfile; calfile.setFile("acme_sn1.dat") calfile.setPath("$ROOT/projects/$PROJECT/cal_files:$ROOT/cal_files");
... while (tsample > calfile.nextTime()) { try { dsm_time_t calTime; float caldata[5]; int n = calfile.readCF(calTime, caldata, 5); for (int i = 0; i < n; i++) coefs[i] = caldata[i]; } catch(const nidas::util::IOException& e) { log(e.what); break; } catch(const nidas::util::ParseException& e) { log(e.what); break; } } // use coefs[] to calibrate sample.
CalFile::CalFile | ( | ) |
References _curline, _reUsers, _staticMutex, nidas::core::getSample(), and setTimeZone().
Referenced by openInclude().
Copy constructor.
Copies the value of getFileName() and getPath() attributes. The CalFile will not be opened in the new copy.
References _curline, _reUsers, _staticMutex, nidas::core::getSample(), and setTimeZone().
CalFile::~CalFile | ( | ) |
Closes the file if necessary.
References _curline, _include, _reCompiled, _reUsers, _staticMutex, close(), freeREs(), and nidas::core::getSample().
void CalFile::close | ( | ) | ||||
throw | ( | ) |
Close file.
An opened CalFile is closed in the destructor, so it is not necessary to call close.
References _fin, _include, _nline, and close().
Referenced by close(), operator=(), readCFInclude(), readTime(), and ~CalFile().
|
staticprivate |
nidas::util::ParseException |
References _dateFormatPreg, _includePreg, _reCompiled, _timeZonePreg, and nidas::core::getSample().
Referenced by parseInclude(), and parseTimeComments().
|
inline |
Have we reached eof.
References _eofState, and _include.
Referenced by readCFNoLock(), readLine(), readTime(), and search().
|
staticprivate |
References _dateFormatPreg, _includePreg, _reCompiled, _timeZonePreg, and nidas::core::getSample().
Referenced by ~CalFile().
nidas::util::InvalidParameterException |
Implements nidas::core::DOMable.
References nidas::core::getSample(), setFile(), setName(), and setPath().
|
inlinestatic |
Return all the paths that have been set in all CalFile instances, in the order they were seen.
These have been separated at the colons.
References _allPaths, _staticMutex, and nidas::core::getSample().
const std::vector< std::string > & CalFile::getCurrentFields | ( | nidas::util::UTime * | time = 0 | ) |
Return the time and fields of the current record, the one last read with readCF().
If there is no current record, then the return vector will be empty and the time will be UTime::MIN. If an include file is being read, then this returns the current fields of the included file.
References _currentFields, _currentTime, _include, and getCurrentFields().
Referenced by getCurrentFields().
|
inline |
Return the full file path of the current file.
References _currentFileName, _include, and getCurrentFileName().
Referenced by nidas::core::VariableConverter::abortCalFile(), nidas::dynld::raf::A2D_Serial::dumpConfig(), getCurrentFileName(), getFields(), nidas::core::Polynomial::parseFields(), parseTime(), nidas::dynld::raf::A2D_Serial::process(), readCFNoLock(), and readLine().
|
inline |
References _currentTime.
|
inline |
References _dateTimeFormat.
int CalFile::getFields | ( | int | begin, |
int | end, | ||
float * | data, | ||
const std::vector< std::string > * | fields = 0 ) |
Parse a range of columns from the fields vector as numbers and store them in the array data
.
begin
is the index of the first field to parse, and end
is one greater than the index of the last field to parse. The first field is index 0. If there are fewer fields than numbers, the remaining numbers are filled with nan. So the data array must point to memory for at least (end - begin) numbers. The return value is the number of fields that were parsed, so it may be less than the number of data values filled in.
Like getField(), throws nidas::util::ParseException if a field cannot be converted to a number.
If fields
is null, then use the same fields as getCurrentFields() would return.
References _curline, _curpos, _currentFields, nidas::core::floatNAN, getCurrentFileName(), getLineNumber(), and nidas::core::getSample().
Referenced by getFloatField(), and readCFNoLock().
const string & CalFile::getFile | ( | ) | const |
References _fileName.
Referenced by nidas::dynld::raf::SyncRecordSource::createHeader(), open(), and nidas::dynld::isff::RebsLinear::toString().
Convert the field at index column
in the fields vector to a number, and return the number.
Throws nidas::util::ParseException if the field cannot be converted to a number, and the message indicates which column caused the error. Column is a 0-based index into fields. If fields
is null, then use the same fields as getCurrentFields() would return.
References getFields().
|
inline |
References _include, _nline, and getLineNumber().
Referenced by getFields(), getLineNumber(), and parseTime().
|
inline |
References _name.
Referenced by PConfig::showCalFiles().
References nidas::core::DOMable::namespaceURI.
Referenced by nidas::dynld::UDPSampleOutput::getProjectDOM(), nidas::core::Dataset::toDOMElement(), nidas::core::ProjectConfig::toDOMElement(), nidas::core::Dataset::toDOMParent(), nidas::core::Datasets::toDOMParent(), nidas::core::ProjectConfig::toDOMParent(), nidas::core::ProjectConfigs::toDOMParent(), nidas::core::DSMConfig::toDOMParent(), nidas::core::DSMSensor::toDOMParent(), nidas::core::Project::toDOMParent(), nidas::core::SampleTag::toDOMParent(), nidas::core::Site::toDOMParent(), nidas::core::ServerSocket::toDOMParent(), nidas::core::Variable::toDOMParent(), nidas::core::Datasets::writeXML(), and nidas::core::ProjectConfigs::writeXML().
const std::string & CalFile::getPath | ( | ) | const |
Set the search path to find the file, and any included files: one or more directory paths separated by colons ':'.
References _path.
Referenced by open(), and nidas::dynld::isff::RebsLinear::toString().
|
inline |
References _nextTime.
Referenced by readCFInclude().
void CalFile::open | ( | ) |
Open the file.
It is not necessary to call open(). If the user has not done an open() it will be done in the first readCF(), or search().
nidas::util::IOException |
References _curline, _curpos, _currentFileName, _eofState, _fin, _nextTime, _path, _sensor, getFile(), getPath(), and ILOG.
Referenced by openInclude(), readLine(), and search().
References _include, _includeTime, _nextTime, _timeAfterInclude, _timeFromInclude, CalFile(), open(), readTime(), search(), and setFile().
Referenced by parseInclude().
|
protected |
If the current calfile record line is an include directive, parse the include filename, open it, and return 1.
Otherwise return 0. It is up to the caller to recurse into the include file to read the next cal record.
References _curline, _curpos, _includePreg, _reCompiled, _staticMutex, compileREs(), nidas::core::getSample(), and openInclude().
Referenced by readCFNoLock().
|
protected |
nidas::util::ParseException |
References _curline, _curpos, _dateTimeFormat, _timeZone, _utcZone, getCurrentFileName(), getLineNumber(), and nidas::core::getSample().
Referenced by readTime(), and search().
|
protected |
Check the current line for special comments with timezone and datetime format settings.
Return true if such a comment was found and handled. Throw ParseException if there is an error with the regular expression matching.
References _curline, _curpos, _dateFormatPreg, _reCompiled, _staticMutex, _timeZonePreg, compileREs(), nidas::core::getSample(), setDateTimeFormat(), and setTimeZone().
Referenced by readLine().
int CalFile::readCF | ( | nidas::util::UTime & | time, |
float * | data, | ||
int | ndata, | ||
std::vector< std::string > * | fields = 0 ) |
Read the time and data from the current record, and return the number of values read.
The return value may be less than ndata, in which case values in data after n will be filled with NANs. As part of this call, the next time in the file is also read, and its result is available with nextTime(). This method uses a mutex so that multi-threaded calls should not result in crashes or unparseable data. However two threads reading the same CalFile will "steal" each other's data, meaning each thread won't read a full copy of the CalFile.
If fields
is not null, then it points to a string vector to which all the fields in the calfile record will be assigned. So all the numeric fields parsed and stored in data
will also be included in fields
, followed by any fields past the last parsed numeric field.
For example, given this calfile line:
Then 9 strings will be added to fields:
"0.00", ..., "1.0", "flipped", but the returned value will still be 8, same as if fields had been null. If a caller only wants string fields, then it can retrieve them like so:
Cal files can have non-numeric columns interspersed with the numeric columns, in which case all the columns can be read into the fields
vector, and then individual fields can be converted to numbers using getField() and getFields().
After successfully reading a record with readCF(), the fields of the current record are also stashed in this CalFile and can be retrieved with getCurrentFields(). The fields are not valid except after calling readCF().
References _mutex, nidas::core::getSample(), and readCFNoLock().
Referenced by readCFInclude().
|
protected |
Internal version of readCF() which reads records from the current include file, if any.
Returns the result from readCF(), or else -1 if the include file has been exhausted of records and closed.
References _fileName, _include, _includeTime, _nextTime, _timeAfterInclude, close(), nidas::util::UTime::format(), nidas::core::getSample(), LOG_VERBOSE, nextTime(), readCF(), and VLOG.
Referenced by readCFNoLock().
|
private |
References _curline, _curpos, _currentFields, _currentTime, _include, _nextTime, eof(), getCurrentFileName(), getFields(), nidas::core::getSample(), nidas::util::UTime::isMin(), parseInclude(), readCFInclude(), readCFNoLock(), and readTime().
Referenced by readCF(), and readCFNoLock().
|
protected |
Read forward to next non-comment line in CalFile.
Place result in _curline, and index of first non-space character in _curpos. Set _eofState=true if that is the case. Also parses special comment lines like below, using parseTimeComments():
References _curline, _curlineLength, _curpos, _eofState, _fin, _nline, eof(), getCurrentFileName(), nidas::core::getSample(), open(), parseTimeComments(), and VLOG.
Referenced by readTime(), and search().
|
private |
Read lines, parsing special comment lines and skipping other comments or blank lines, until a record line is found.
Then parse and return the time from that record. On EOF, the returned time will be a huge value, far off in the mega-distant future. Does not return an EOFException on EOF. After parsing the time from a record, curline contains that record, and curpos points to the character after the datetime field. Also sets _nextTime to the returned time.
References _nextTime, close(), eof(), parseTime(), and readLine().
Referenced by openInclude(), and readCFNoLock().
n_u::UTime CalFile::search | ( | const nidas::util::UTime & | tsearch | ) |
Search forward in a file, returning the time of the last record in the file with a time less than or equal to tsearch.
The time is available by calling nextTime(). The next call to readCF() will return that record.
References _eofState, _fin, _mutex, _nextTime, _nline, eof(), nidas::core::getSample(), open(), parseTime(), and readLine().
Referenced by openInclude().
Set the format for reading the date & time from the file.
If a "dateFormat" comment is found at the beginning of the file, this attribute will be set to that value.
References _dateTimeFormat, _fileName, nidas::core::getSample(), nidas::util::replaceCharsIn(), and VLOG.
Referenced by parseTimeComments().
Set the DSMSensor associated with this CalFile.
CalFile may need this in order to substitute for tokens like $DSM and $HEIGHT in the file or path names. Otherwise it is not necessary to setDSMSensor.
References _sensor, and nidas::core::getSample().
Referenced by nidas::core::SampleTag::fromDOMElement().
Set the base name of the file to be opened.
References _fileName, and nidas::core::getSample().
Referenced by fromDOMElement(), and openInclude().
An instance of CalFile can have a name.
Then more than one CalFile can be associated with an object, such as a DSMSensor, and it can differentiate them by name.
References _name, and nidas::core::getSample().
Referenced by fromDOMElement().
Set the search path to find the file, and any included files: one or more directory paths separated by colons ':'.
References _allPaths, _path, _staticMutex, and nidas::core::getSample().
Referenced by fromDOMElement().
Set the timezone for the dates & times read from the file.
If a "timeZone" comment is found at the beginning of the file, this attribute will be set to that value.
References _fileName, _timeZone, _utcZone, nidas::core::getSample(), and VLOG.
Referenced by CalFile(), CalFile(), operator=(), and parseTimeComments().
|
virtualinherited |
Add my content into a DOMElement.
xercesc::DOMException |
Reimplemented in nidas::core::DSMConfig, nidas::core::DSMSensor, nidas::core::Project, nidas::core::SampleTag, nidas::core::Site, nidas::core::ServerSocket, and nidas::core::Variable.
Referenced by nidas::core::ServerSocket::toDOMParent().
|
virtualinherited |
Create a DOMElement and append it to the parent.
xercesc::DOMException |
Reimplemented in nidas::core::DSMConfig, nidas::core::DSMSensor, nidas::core::Project, nidas::core::SampleTag, nidas::core::Site, nidas::core::ServerSocket, and nidas::core::Variable.
|
staticprivate |
Referenced by getAllPaths(), and setPath().
|
private |
Referenced by CalFile(), CalFile(), getFields(), open(), parseInclude(), parseTime(), parseTimeComments(), readCFNoLock(), readLine(), and ~CalFile().
|
private |
Referenced by readLine().
|
private |
Referenced by getFields(), open(), operator=(), parseInclude(), parseTime(), parseTimeComments(), readCFNoLock(), and readLine().
|
private |
Referenced by getCurrentFields(), getFields(), and readCFNoLock().
|
private |
Referenced by getCurrentFileName(), and open().
|
private |
Referenced by getCurrentFields(), getCurrentTime(), and readCFNoLock().
|
staticprivate |
Referenced by compileREs(), freeREs(), and parseTimeComments().
|
private |
Referenced by getDateTimeFormat(), operator=(), parseTime(), and setDateTimeFormat().
|
private |
Referenced by eof(), open(), operator=(), readLine(), and search().
|
private |
Referenced by getFile(), operator=(), readCFInclude(), setDateTimeFormat(), setFile(), and setTimeZone().
|
private |
Referenced by close(), open(), readLine(), and search().
|
private |
Referenced by close(), eof(), getCurrentFields(), getCurrentFileName(), getLineNumber(), openInclude(), operator=(), readCFInclude(), readCFNoLock(), and ~CalFile().
|
staticprivate |
Referenced by compileREs(), freeREs(), and parseInclude().
|
private |
Time stamp of include "file" record.
Referenced by openInclude(), and readCFInclude().
|
private |
|
private |
Referenced by getName(), operator=(), and setName().
|
private |
Referenced by nextTime(), open(), openInclude(), readCFInclude(), readCFNoLock(), readTime(), and search().
|
private |
Referenced by close(), getLineNumber(), operator=(), readLine(), and search().
|
private |
Referenced by getPath(), open(), operator=(), and setPath().
Referenced by compileREs(), freeREs(), parseInclude(), parseTimeComments(), and ~CalFile().
|
staticprivate |
Referenced by CalFile(), CalFile(), and ~CalFile().
Referenced by getDSMSensor(), open(), operator=(), and setDSMSensor().
|
staticprivate |
Referenced by CalFile(), CalFile(), getAllPaths(), parseInclude(), parseTimeComments(), setPath(), and ~CalFile().
|
private |
Time stamp of record after include "file".
Referenced by openInclude(), and readCFInclude().
|
private |
Time stamp of last record in include file with time <= _includeTime.
Referenced by openInclude().
|
private |
Referenced by getTimeZone(), parseTime(), and setTimeZone().
|
staticprivate |
Referenced by compileREs(), freeREs(), and parseTimeComments().
|
private |
Referenced by parseTime(), and setTimeZone().
|
staticprivateinherited |
Referenced by nidas::core::DOMable::getNamespaceURI().