WSL/SLF GitLab Repository

Commit 886f3a28 authored by Mathias Bavay's avatar Mathias Bavay
Browse files

The DEMObject subset constructor was broken, it has been fixed. It involved...

The DEMObject subset constructor was broken, it has been fixed. It involved creating a subset method in the arrays classes.

The Coord class now supports using the given UTM zone when converting from lat/long to UTM. If the computed zone does not match the one requested in the io.ini, it prints a warning but uses the user-supplied zone.

A first implementation of readStationData for SMETIO has been done. 

Some documentation has been added for plugin development
parent 7740ce75
......@@ -60,13 +60,31 @@ template <class T> class Array2DProxy {
template<class T> class Array2D {
public:
Array2D();
/**
* A constructor that creates an array of a given size
* @param anx number of columns of the new array
* @param any number of rows of the new array
*/
Array2D(const unsigned int& anx, const unsigned int& any);
/**
* A constructor that creates an array filled with constant values
* @param anx number of columns of the new array
* @param any number of rows of the new array
* @param init initial value to fill the array with
*/
Array2D(const unsigned int& anx, const unsigned int& any, const T& init);
/**
* A constructor that can be used to create an Array2D object that is contained in the
* one passed as _array2D argument. The resulting Array2D object is a by value copy of
* a subplane of the plane spanned by the _array2D
* @param _array2D array containing to extract the values from
* @param _nx lower left corner cell X index
* @param _ny lower left corner cell Y index
* @param _ncols number of columns of the new array
* @param _nrows number of rows of the new array
*/
Array2D(const Array2D<T>& _array2D, const unsigned int& _nx, const unsigned int& _ny,
const unsigned int& _ncols, const unsigned int& _nrows);
......@@ -75,6 +93,11 @@ template<class T> class Array2D {
* @brief A method that can be used to cut out a subplane of an existing Array2D object
* that is passed as _array2D argument. The resulting Array2D object is a by value copy of
* a subplane of the plane spanned by the _array2D
* @param _array2D array containing to extract the values from
* @param _nx lower left corner cell X index
* @param _ny lower left corner cell Y index
* @param _ncols number of columns of the new array
* @param _nrows number of rows of the new array
*/
void subset(const Array2D<T>& _array2D, const unsigned int& _nx, const unsigned int& _ny,
const unsigned int& _ncols, const unsigned int& _nrows);
......
......@@ -89,17 +89,55 @@ template<class T> class Array3D {
/**
* A constructor that can be used to create an Array3D object that is contained in the
* one passed as _array3D argument. The resulting Array3D object is a by value copy of
* a subspace of the space spanned by the _array3D
* a subvolume of the volume spanned by the _array3D
* @param _array3D array containing to extract the values from
* @param _nx lower left corner cell X index
* @param _ny lower left corner cell Y index
* @param _nz lower left corner cell Z index
* @param _ncols number of columns of the new array
* @param _nrows number of rows of the new array
* @param _ndepth number of depths of the new array
*/
Array3D(const Array3D<T>& _array3D,
const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz,
const unsigned int& _cols, const unsigned int& _nrows, const unsigned int& _ndepth);
Array3D(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz);
Array3D(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz, const T& _init);
void resize(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz);
void resize(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz, const T& _init);
void size(unsigned int& _nx, unsigned int& _ny, unsigned int& _nz) const;
const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz,
const unsigned int& _ncols, const unsigned int& _nrows, const unsigned int& _ndepth);
/**
* A constructor that creates an array of a given size
* @param anx number of columns of the new array
* @param any number of rows of the new array
* @param anz number of rows of the new array
*/
Array3D(const unsigned int& anx, const unsigned int& any, const unsigned int& anz);
/**
* A constructor that creates an array filled with constant values
* @param anx number of columns of the new array
* @param any number of rows of the new array
* @param anz number of depths of the new array
* @param init initial value to fill the array with
*/
Array3D(const unsigned int& anx, const unsigned int& any, const unsigned int& anz, const T& init);
/**
* A method that can be used to create an Array3D object that is contained in the
* one passed as _array3D argument. The resulting Array3D object is a by value copy of
* a subvolume of the volume spanned by the _array3D
* @param _array3D array containing to extract the values from
* @param _nx lower left corner cell X index
* @param _ny lower left corner cell Y index
* @param _nz lower left corner cell Z index
* @param _ncols number of columns of the new array
* @param _nrows number of rows of the new array
* @param _ndepth number of depths of the new array
*/
void subset(const Array3D<T>& _array3D,
const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz,
const unsigned int& _ncols, const unsigned int& _nrows, const unsigned int& _ndepth);
void resize(const unsigned int& anx, const unsigned int& any, const unsigned int& anz);
void resize(const unsigned int& anx, const unsigned int& any, const unsigned int& anz, const T& init);
void size(unsigned int& anx, unsigned int& any, unsigned int& anz) const;
void clear();
/**
......@@ -186,8 +224,15 @@ template<class T> Array3D<T>::Array3D() {
}
template<class T> Array3D<T>::Array3D(const Array3D<T>& _array3D,
const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz,
const unsigned int& _ncols, const unsigned int& _nrows, const unsigned int& _ndepth)
const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz,
const unsigned int& _ncols, const unsigned int& _nrows, const unsigned int& _ndepth)
{
subset(_array3D, _nx, _ny, _nz, _ncols, _nrows, _ndepth);
}
template<class T> void Array3D<T>::subset(const Array3D<T>& _array3D,
const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz,
const unsigned int& _ncols, const unsigned int& _nrows, const unsigned int& _ndepth)
{
if (((_nx+_ncols) > _array3D.nx) || ((_ny+_nrows) > _array3D.ny) || ((_nz+_ndepth) > _array3D.nz))
......@@ -209,44 +254,44 @@ template<class T> Array3D<T>::Array3D(const Array3D<T>& _array3D,
}
}
template<class T> Array3D<T>::Array3D(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz) {
resize(_nx, _ny, _nz);
template<class T> Array3D<T>::Array3D(const unsigned int& anx, const unsigned int& any, const unsigned int& anz) {
resize(anx, any, anz);
}
template<class T> Array3D<T>::Array3D(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz, const T& _init) {
resize(_nx, _ny, _nz, _init);
template<class T> Array3D<T>::Array3D(const unsigned int& anx, const unsigned int& any, const unsigned int& anz, const T& init) {
resize(anx, any, anz, init);
}
template<class T> void Array3D<T>::resize(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz) {
template<class T> void Array3D<T>::resize(const unsigned int& anx, const unsigned int& any, const unsigned int& anz) {
clear();
if ((_nx > 0) && (_ny > 0) && (_nz > 0)) {
vecData.resize(_nx*_ny*_nz);
nx = _nx;
ny = _ny;
nz = _nz;
if ((anx > 0) && (any > 0) && (anz > 0)) {
vecData.resize(anx*any*anz);
nx = anx;
ny = any;
nz = anz;
nxny = nx*ny;
} else {
throw IndexOutOfBoundsException("", AT);
}
}
template<class T> void Array3D<T>::resize(const unsigned int& _nx, const unsigned int& _ny, const unsigned int& _nz, const T& _init) {
resize(_nx, _ny, _nz);
template<class T> void Array3D<T>::resize(const unsigned int& anx, const unsigned int& any, const unsigned int& anz, const T& init) {
resize(anx, any, anz);
for (unsigned int ii=0; ii<nz; ii++) {
for (unsigned int jj=0; jj<ny; jj++) {
for (unsigned int kk=0; kk<nx; kk++) {
operator()(kk,jj,ii) = _init; //Running through the vector in order of memory alignment
operator()(kk,jj,ii) = init; //Running through the vector in order of memory alignment
}
}
}
}
template<class T> void Array3D<T>::size(unsigned int& _nx, unsigned int& _ny, unsigned int& _nz) const {
_nx=nx;
_ny=ny;
_nz=nz;
template<class T> void Array3D<T>::size(unsigned int& anx, unsigned int& any, unsigned int& anz) const {
anx=nx;
any=ny;
anz=nz;
}
template<class T> void Array3D<T>::clear() {
......
......@@ -538,15 +538,7 @@ short int Coords::getEPSG() const {
//UTM Zone information
short int zoneNumber;
char zoneLetter;
if ((sscanf(coordparam.c_str(), "%hd%c", &zoneNumber, &zoneLetter) < 2) &&
(sscanf(coordparam.c_str(), "%hd %c)", &zoneNumber, &zoneLetter) < 2)) {
throw InvalidFormatException("Can not parse given UTM zone: "+coordparam,AT);
}
zoneLetter = toupper(zoneLetter); //just in case... (sorry for the pun!)
if(zoneLetter=='Y' || zoneLetter=='Z' || zoneLetter=='A' || zoneLetter=='B') {
//Special zones for the poles: we should NOT use UTM in these regions!
throw InvalidFormatException("Invalid UTM zone: "+coordparam+" (trying to use UTM in polar regions)",AT);
}
parseUTMZone(coordparam, zoneLetter, zoneNumber);
if(zoneLetter >= 'M') {
//northern hemisphere
return (32600+zoneNumber);
......@@ -882,7 +874,15 @@ void Coords::WGS84_to_UTM(double lat_in, double long_in, double& east_out, doubl
long_in = fmod(long_in+360.+180., 360.) - 180.; //normalized to [-180. ; 180.[
const double Long = long_in * to_rad;
const double Lat = lat_in * to_rad;
const int zoneNumber = getUTMZone(lat_in, long_in, zone);
int zoneNumber = getUTMZone(lat_in, long_in, zone);
short int in_zoneNumber;
char in_zoneLetter;
parseUTMZone(coordparam, in_zoneLetter, in_zoneNumber);
if(in_zoneNumber!=zoneNumber) {
std::cerr << "[W] requested UTM zone is not appropriate for the given coordinates. Normally, It should be zone ";
std::cerr << zoneNumber << "\n";
zoneNumber = in_zoneNumber;
}
const double long0 = (double)((zoneNumber - 1)*6 - 180 + 3) * to_rad; //+3 puts origin in middle of zone
//Geometrical parameters
......@@ -937,15 +937,7 @@ void Coords::UTM_to_WGS84(double east_in, double north_in, double& lat_out, doub
//UTM Zone information
short int zoneNumber;
char zoneLetter;
if ((sscanf(coordparam.c_str(), "%hd%c", &zoneNumber, &zoneLetter) < 2) &&
(sscanf(coordparam.c_str(), "%hd %c)", &zoneNumber, &zoneLetter) < 2)) {
throw InvalidFormatException("Can not parse given UTM zone: "+coordparam,AT);
}
zoneLetter = toupper(zoneLetter); //just in case... (sorry for the pun!)
if(zoneLetter=='Y' || zoneLetter=='Z' || zoneLetter=='A' || zoneLetter=='B') {
//Special zones for the poles: we should NOT use UTM in these regions!
throw InvalidFormatException("Invalid UTM zone: "+coordparam+" (trying to use UTM in polar regions)",AT);
}
parseUTMZone(coordparam, zoneLetter, zoneNumber);
//set reference parameters: central meridian of the zone, true northing and easting
//please note that the special zones still use the reference meridian as given by their zone number (ie: even if it might not be central anymore)
......@@ -955,7 +947,7 @@ void Coords::UTM_to_WGS84(double east_in, double north_in, double& lat_out, doub
}
east_in -= 500000.0; //longitude offset: x coordinate is relative to central meridian
//calculating footprint latitude fp
//calculating footprint latitude fp (it should be done using a few iterations)
const double arc = north_in/k0; //Meridional arc
const double mu = arc / (a*(1.-e2/4.-3.*e2*e2/64.-5.*e2*e2*e2/256.));
const double e1 = (1.-b/a) / (1.+b/a); //simplification of [1 - (1 - e2)1/2]/[1 + (1 - e2)1/2]
......@@ -977,12 +969,28 @@ void Coords::UTM_to_WGS84(double east_in, double north_in, double& lat_out, doub
const double Q2 = 0.5*D*D;
const double Q3 = (5. + 3.*T1 + 10.*C1 - 4.*C1*C1 - 9.*eP2) * 1./24.*D*D*D*D;
const double Q4 = (61. + 90.*T1 + 298.*C1 + 45.*T1*T1 - 3.*C1*C1 - 252.*eP2) * 1./720.*D*D*D*D*D*D;
//const double Q4extra = (1385. + 3633.*T1 + 4095.*T1*T1 + 1575.*T1*T1*T1) * 1./40320.*D*D*D*D*D*D*D*D;
const double Q5 = D;
const double Q6 = (1. + 2.*T1 + C1) * 1./6.*D*D*D;
const double Q7 = (5. - 2.*C1 + 28.*T1 - 3.*C1*C1 + 8.*eP2 + 24.*T1*T1) * 1./120.*D*D*D*D*D;
//const double Q7extra = (61. + 662.*T1 + 1320.*T1*T1 +720.*T1*T1*T1) * 1./5040.*D*D*D*D*D*D*D;
lat_out = (fp - Q1 * (Q2 - Q3 + Q4 /*+Q4extra*/))*to_deg;
long_out = (double)long0 + ((Q5 - Q6 + Q7 /*-Q7extra*/)/cos(fp))*to_deg;
}
lat_out = (fp - Q1 * (Q2 - Q3 + Q4))*to_deg;
long_out = (double)long0 + ((Q5 - Q6 + Q7)/cos(fp))*to_deg;
void Coords::parseUTMZone(const std::string& zone_info, char& zoneLetter, short int& zoneNumber) const
{ //helper method: parse a UTM zone specification string into letter and number
if ((sscanf(zone_info.c_str(), "%hd%c", &zoneNumber, &zoneLetter) < 2) &&
(sscanf(zone_info.c_str(), "%hd %c)", &zoneNumber, &zoneLetter) < 2)) {
throw InvalidFormatException("Can not parse given UTM zone: "+zone_info,AT);
}
zoneLetter = toupper(zoneLetter); //just in case... (sorry for the pun!)
if(zoneLetter=='Y' || zoneLetter=='Z' || zoneLetter=='A' || zoneLetter=='B') {
//Special zones for the poles: we should NOT use UTM in these regions!
throw InvalidFormatException("Invalid UTM zone: "+zone_info+" (trying to use UTM in polar regions)",AT);
}
}
/**
......
......@@ -118,6 +118,8 @@ class Coords {
void WGS84_to_NULL(double lat_in, double long_in, double& east_out, double& north_out) const;
void NULL_to_WGS84(double east_in, double north_in, double& lat_out, double& long_out) const;
void parseUTMZone(const std::string& zone_info, char& zoneLetter, short int& zoneNumber) const;
//Distances calculations
void distance(const Coords& destination, double& distance, double& bearing) const;
double cosineDistance(const double& lat1, const double& lon1, const double& lat2, const double& lon2, double& alpha) const;
......
......@@ -119,22 +119,54 @@ DEMObject::DEMObject(const Grid2DObject& _dem, const bool& _update, const slope_
* @param _algorithm specify the default algorithm to use for slope computation (default=DFLT)
*/
DEMObject::DEMObject(const DEMObject& _dem, const unsigned int& _nx, const unsigned int& _ny,
const unsigned int& _ncols, const unsigned int& _nrows, const bool& _update, const slope_type& _algorithm)
: Grid2DObject(_dem, _nx,_ny, _ncols,_nrows), slope(_dem.slope,_nx,_ny, _ncols,_nrows),
azi(_dem.azi,_nx,_ny, _ncols,_nrows), curvature(_dem.curvature,_nx,_ny, _ncols,_nrows),
Nx(_dem.Nx,_nx,_ny, _ncols,_nrows), Ny(_dem.Ny,_nx,_ny, _ncols,_nrows), Nz(_dem.Nz,_nx,_ny, _ncols,_nrows)
const unsigned int& _ncols, const unsigned int& _nrows,
const bool& _update, const slope_type& _algorithm)
: Grid2DObject(_dem, _nx,_ny, _ncols,_nrows),
slope(), azi(), curvature(), Nx(), Ny(), Nz()
{
if ((_ncols==0) || (_nrows==0)) {
throw InvalidArgumentException("requesting a subset of 0 columns or rows for DEMObject", AT);
}
//handling of the update properties
slope_failures = curvature_failures = 0;
update_flag = INT_MAX;
update_flag = _dem.getUpdatePpt();
setDefaultAlgorithm(_algorithm);
if(_update==false) {
updateAllMinMax();
} else {
if(_update==true) {
//if the object is in automatic update, then we only process the arrays according to
//the update_flag
update(_algorithm);
} else {
//if the object is NOT in automatic update, we manually copy all non-empty arrays
//from the original set
unsigned int nx, ny;
_dem.slope.size(nx, ny);
if(nx>0 && ny>0) {
slope.subset(_dem.slope,_nx,_ny, _ncols,_nrows);
}
_dem.azi.size(nx, ny);
if(nx>0 && ny>0) {
azi.subset(_dem.azi,_nx,_ny, _ncols,_nrows);
}
_dem.curvature.size(nx, ny);
if(nx>0 && ny>0) {
curvature.subset(_dem.curvature,_nx,_ny, _ncols,_nrows);
}
_dem.Nx.size(nx, ny);
if(nx>0 && ny>0) {
Nx.subset(_dem.Nx,_nx,_ny, _ncols,_nrows);
}
_dem.Ny.size(nx, ny);
if(nx>0 && ny>0) {
Ny.subset(_dem.Ny,_nx,_ny, _ncols,_nrows);
}
_dem.Nz.size(nx, ny);
if(nx>0 && ny>0) {
Nz.subset(_dem.Nz,_nx,_ny, _ncols,_nrows);
}
updateAllMinMax();
}
}
......@@ -152,7 +184,7 @@ void DEMObject::setUpdatePpt(const update_type& in_update_flag) {
* @brief Get the properties that will be calculated by the object when updating
* @return combination of flags set with the binary "|" operator
*/
int DEMObject::getUpdatePpt() {
int DEMObject::getUpdatePpt() const {
return update_flag;
}
......
......@@ -70,22 +70,22 @@ class DEMObject : public Grid2DObject {
DEMObject(const slope_type& _algorithm=DFLT);
DEMObject(const unsigned int& ncols_in, const unsigned int& nrows_in,
const double& cellsize_in, const Coords& llcorner_in, const slope_type& _algorithm=DFLT);
const double& cellsize_in, const Coords& llcorner_in, const slope_type& _algorithm=DFLT);
DEMObject(const unsigned int& ncols_in, const unsigned int& nrows_in,
const double& cellsize_in, const Coords& llcorner_in, const Array2D<double>& altitude_in,
const bool& _update=true, const slope_type& _algorithm=DFLT);
const double& cellsize_in, const Coords& llcorner_in, const Array2D<double>& altitude_in,
const bool& _update=true, const slope_type& _algorithm=DFLT);
DEMObject(const Grid2DObject& dem_in, const bool& _update=true, const slope_type& _algorithm=DFLT);
DEMObject (const DEMObject& _dem,
const unsigned int& _nx, const unsigned int& _ny, //Point in the plane
const unsigned int& _ncols, const unsigned int& _nrows, //dimensions of the sub-plane
const bool& _update=true, const slope_type& _algorithm=DFLT);
const unsigned int& _nx, const unsigned int& _ny, //Point in the plane
const unsigned int& _ncols, const unsigned int& _nrows, //dimensions of the sub-plane
const bool& _update=true, const slope_type& _algorithm=DFLT);
void setDefaultAlgorithm(const slope_type& _algorithm);
void setUpdatePpt(const update_type& in_update_flag);
int getUpdatePpt();
int getUpdatePpt() const;
void update(const std::string& algorithm);
void update(const slope_type& algorithm=DFLT);
......
......@@ -67,10 +67,10 @@ class Grid2DObject {
*/
Grid2DObject();
Grid2DObject(const unsigned int& ncols, const unsigned int& nrows,
const double& cellsize, const Coords& _llcorner);
const double& cellsize, const Coords& _llcorner);
Grid2DObject(const unsigned int& ncols, const unsigned int& nrows,
const double& cellsize, const Coords& _llcorner, const Array2D<double>& grid2D_in);
const double& cellsize, const Coords& _llcorner, const Array2D<double>& grid2D_in);
/**
* @brief constructs an object as a subset of another grid object
......@@ -81,8 +81,8 @@ class Grid2DObject {
* @param _nrows (const unsigned int) number of rows of the subset
*/
Grid2DObject(const Grid2DObject& _grid2Dobj,
const unsigned int& _nx, const unsigned int& _ny, //Point in the plane
const unsigned int& _ncols, const unsigned int& _nrows); //dimensions of the sub-plane
const unsigned int& _nx, const unsigned int& _ny, //Point in the plane
const unsigned int& _ncols, const unsigned int& _nrows); //dimensions of the sub-plane
/**
* @brief Compute the positional parameters that are not already known
......@@ -113,7 +113,7 @@ class Grid2DObject {
* @param _llcorner lower left corner point
*/
void set(const unsigned int& ncols, const unsigned int& nrows,
const double& cellsize, const Coords& _llcorner);
const double& cellsize, const Coords& _llcorner);
/**
* @brief Set all variables in one go. Notably the member grid2D of type
* Array2D\<double\> will be destroyed and recreated to size ncols x nrows.
......@@ -124,7 +124,7 @@ class Grid2DObject {
* @param grid2D_in (CArray\<double\>&) grid to be copied by value
*/
void set(const unsigned int& ncols, const unsigned int& nrows,
const double& cellsize, const Coords& _llcorner, const Array2D<double>& grid2D_in); //TODO: const CArray would be better...
const double& cellsize, const Coords& _llcorner, const Array2D<double>& grid2D_in); //TODO: const CArray would be better...
/**
* @brief check if the current Grid2DObject has the same geolocalization attributes
......@@ -143,9 +143,9 @@ class Grid2DObject {
protected:
void setValues(const unsigned int& ncols, const unsigned int& nrows,
const double& cellsize, const Coords& _llcorner);
const double& cellsize, const Coords& _llcorner);
void setValues(const unsigned int& _ncols, const unsigned int& _nrows,
const double& _cellsize);
const double& _cellsize);
/**
* @brief Converts WGS84 coordinates into grid coordinates (i,j)
......
......@@ -45,7 +45,7 @@ namespace mio {
* }
* @endcode
*
* It is the responsibility of the plugin to properly convert the units toward the SI as used in MeteoIO (see the MeteoData class for a list of parameters and their units)
* It is the responsibility of the plugin to properly convert the units toward the SI as used in MeteoIO (see the MeteoData class for a list of parameters and their units). Moreover, it is required by the BufferedIOHandler that each plugin that implements readMeteoData @em also implements the readStationData method. This is required so that the metadata is available even if not data exists for the requested time period.
*
* The meteorological data must be returned in a vector of vectors of MeteoData (and similarly, of StationData in order to provide the metadata). This consists of building a vector of MeteoData objects, each containing a set of measurements for a given timestamp, at a given location. This vector that contains the time series at one specific location is then added to a vector (pushed) that will then contain all locations.
* \image html vector_vector.png "vector of vector structure"
......@@ -66,6 +66,14 @@ namespace mio {
* - keywords, listing (with a brief description) the keywords that are recognized by the plugin for its configuration
*
* The internal documentation of the plugin can remain as normal C++ comments (since they are addressed to the maintainer of the plugin).
*
* @section plugins_testing Plugins testing and validation
* In order to check that a plugin operates properly, developers are invited to test the following (among others), for a plugin that reads meteorological data (these tests can be performed using the example code <a href="../../doc/examples/meteo_reading.cc">doc/examples/meteo_reading.cc</a>):
* - request one time stamp part of the original data set
* - request one time stamp within the period of the original data set, but not matching an existing time stamp
* - request a data point @em before the original data set
* - request a data point @em after the original data set
* - request a data point at the end of a very large data set (tens of Mb) and check that memory consumption remains the same as when requesting a data point at the begining of the data set (ie: that the memory for one buffer is used, but that the temporary memory usage of the plugin does not increase with the amount of data it has to parse before returning it to the BufferedIOHandler)
*/
/**
......
......@@ -185,10 +185,49 @@ void SMETIO::readAssimilationData(const Date& /*date_in*/, Grid2DObject& /*da_ou
throw IOException("Nothing implemented here", AT);
}
void SMETIO::readStationData(const Date&, std::vector<StationData>& /*vecStation*/)
{
//Nothing so far
throw IOException("Nothing implemented here", AT);
void SMETIO::readStationData(const Date&, std::vector<StationData>& vecStation)
{//big HACK: this is a barbaric code duplication!! Plus it should support coordinates in the data
unsigned int startindex=0, endindex=vecFiles.size();
vecStation.clear();
//Now loop through all requested stations, open the respective files and parse them
for (unsigned int ii=startindex; ii<endindex; ii++){
bool isAscii = true;
string filename = vecFiles.at(ii); //filename of current station
if (!IOUtils::fileExists(filename))
throw FileNotFoundException(filename, AT);
fin.clear();
fin.open (filename.c_str(), ios::in);
if (fin.fail())
throw FileAccessException(filename, AT);
char eoln = IOUtils::getEoln(fin); //get the end of line character for the file
//Go through file, save key value pairs
string line="";
std::vector<std::string> tmpvec, vecDataSequence;
double timezone = 0.0;
bool locationInHeader = false;
StationData sd;
try {
//1. Read signature
getline(fin, line, eoln); //read complete signature line
IOUtils::stripComments(line);
IOUtils::readLineToVec(line, tmpvec);
checkSignature(tmpvec, filename, isAscii);
//2. Read Header
readHeader(eoln, filename, locationInHeader, timezone, sd, vecDataSequence);
cleanup();
} catch(std::exception& e) {
cleanup();
throw;
}
vecStation.push_back(sd);
}
}
void SMETIO::parseInputOutputSection()
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment