/***************************************************************************
* Copyright (C) 2005 by Nicolas PASCAL *
* nicolas.pascal@icare.univ-lille1.fr *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/***************************************************************************
* History : *
* 25/07/05 : start *
***************************************************************************/
#ifndef HDFFILEDATA_H
#define HDFFILEDATA_H
#define HDFFILEDATA_TRACE 0
#include "filedatareader.h"
#include "Hdf_file.hpp"
#include "hdffilemetadata.h"
#include "netcdf.h"
#include
#include
static const float32 VAR_FILL_VALUE=-DBL_MAX;
/**
Manage the opening, reading, and accessing to the data in a HDF File.
This class encapsulates the Hdf_file class, developped by Fabrice Ducos (fabrice.ducos@icare.univ-lille1.fr), which is a lower level interface to HDF.
How to do some useful actions :
load the data of a whole sds
-> in a C way (with static arrays)
HDFFileData my_hdf=HDFFileData("path_to_desired_hdf_file"); // open the file for reading
float32 *data =NULL; // define buffer where to put the read data
data=read_data(static_cast(data),"Name_Of_The_Sds"); // read the sds' data
make your stuff with the data here
delete[] data; // don't forget to free the data after use
Some remarks :
- data can either be NULL or allocated by the user. If NULL, the method manages the allocations, but the caller must free the data after use.
-> in a C++ way (with STL's vectors)
HDFFileData my_hdf=HDFFileData("path_to_desired_hdf_file"); // open the file for reading
Vector \< T \> *v_data=get_value_XD\("Name_Of_The_Sds"); // fill a vector with the read data
make your stuff with the data vector here
delete v_data; // don't forget to free the data after use
Some remarks :
- X is 1,2 or 3 : the dimension of the returned vector (in fact it returns a pointer to a vector). If 1, it will be a vector<\T> *, if 2 a vector\< vector \ > *...
- T is the type of the read data.
@author Nicolas PASCAL (nicolas.pascal@icare.univ-lille1.fr)
@version 1.0
*/
class HDFFileData : public FileDataReader {
/**
generic methods called by get_value_0D,get_value_1D,get_value_2D. Don't use it directly.
*/
template
T* get_value( const char * sds_name = "Height", int *start = NULL, int *stride = NULL, int *edges = NULL, int rank = -1);
/**
Returns the HDF type_code of the sds named "sds_name". Returns -1 if this sds doesn't exist.
@param sds_name string : the name of the desired sds
@return the HDF type_code of the given sds int32.
*/
const int32 get_sds_type_code( const string & sds_name );
protected:
/**
the lower level access class to the file we are working on.
Can be NULL. In this case, to access the data, call the load_hdf_file method first
*/
Hdf_file *hdf_file;
/**
a tree representing the metadata of the file.
Can be NULL. In this case, to access the data, call the load_hdf_metadata method first
*/
HDFFileMetaData *metadata;
/**
find the indexes of the values that are the nearest to val. REM if the return vector have many indexes, the values at those indexes are equal.
@param v_data the vector that contains the data to be processed
@param val the value we are searching for the nearest values in v_data
@return a vector containing the indexes of the values that are the nearest to val in v_data
*/
template
const vector get_nearest_index(const vector& v_data, const T &val = T(0));
/**
* search in a vector the nearest value to val, and retrun its index
* @param data the vector where must be processed the search
* @param val the value wa are searching for the nearset one
* @return the index of the nearest vector value. -1 in case of problem, for example if the data are empty.
*/
template
const int get_nearest_index(const vector *data, const T val);
/**
* search in a vector the nearest value to val, and retrun its index
* @param data the array where must be processed the search
* @param data_size the number of values of the array
* @param val the value wa are searching for the nearset one
* @return the index of the nearest vector value. -1 in case of problem, for example if the data are empty.
*/
template
const int get_nearest_index(const T* data = NULL, const int data_size = 0, const T val = T(0));
/**
* initialize NULL parametres in read_data methods for a specific sds :
* - set rank size to the sds one
* - allocate edges and set it to hte whole sds size
* - allocate start to the rank size and set it to 0
*/
void init_read_write_null_input_param(const char* sds_name, int *&start, int *&stride, int *&edges, int &rank, bool * initialized_values);
/**
* free the allocations made by the init_read_write_null_input_param methods
*/
void free_read_write_allocations( const bool *are_limits_initialized, int *start, int *stride, int *edges );
const bool check_read_write_limits(const char* sds_name, int *start, int *stride, int *edges, const int rank);
public:
/*********************
** CONSTRUCTORS **
*********************/
/**
* @brief Open and initialize the file.
* @param _name the filename of the file to be opened (including its path). Ex : "/home/kiki/my_file.hdf"
* @param mode the opening mode : "r", "w" or "rw". At this time, only the reading "r" mode is fully implemented
* @param open_file tell wether the file must be opened during the instantiation or not
*/
HDFFileData(const string &name="",const string &mode="r", const bool open_file = false);
/**
* @brief Copy constructor.
* @param hfd the HDFFileData object to be recopied.
*/
HDFFileData(const HDFFileData &hfd);
/**
* @brief Destructor
*/
virtual ~HDFFileData();
/**
* @brief Affectation.
* @param hfd the HDFFileData object to be recopied.
*/
HDFFileData &operator= (const HDFFileData &hfd);
/**
* @brief accessor to the Hdf_file object.
* @return a pointer to Hdf_file object used.
*/
Hdf_file * get_hdf_file();
/**
* @brief open the hdf file in reading mode.
* Instantiates a Hdf_file object.
*/
void load_hdf_file();
/**
* @brief close the hdf file, and free the ressources used by it
*/
void free_hdf_file();
/**
* @brief Check if the hdf file has already been loaded
*/
const bool is_hdf_file_loaded();
/**
* @brief access to the HDF file metadata.
* @return a pointer to HDFFileMetaData object. If the metadata haven't been loaded using the load_metadata method, it will return NULL.
*/
HDFFileMetaData* get_metadata();
/**
* @brief Read the metadata contained in the hdf file and put them in a tree.
*/
void load_hdf_metadata();
/**
* @brief Release the metadata tree
* If the metadata haven't been loaded, nothing's done
*/
void free_hdf_metadata();
/**
* @brief Check if the metadata' tree have already been constructed
* @return true if the metadata have already been loaded
*/
const bool is_hdf_metadata_loaded();
/**
* @brief read the fill value of the sds given in parametre
* @param sds_name the name of the sds where to read the fill value
* @param fill_value (output) where to store the read value
*/
virtual void get_dataset_fill_value(const string &sds_name, void* fill_value);
/**
* @brief access the size of the given sds
* @param sds_name the name of the sds
* @return a vector that contains the dimensions of the sds in each direction. Use return_vector.size() to know the rank of the sds
*/
vector get_sds_dimension(const string &sds_name);
/**
* @brief return the given dataset size along each axis
* @param ds_name [IN] dataset name
* @return the axis dimensions in ordering [..., Z, Y, X]. Use return_vector.size() to know the rank of the sds
*/
virtual vector get_dataset_dimension(const string &sds_name) {
return get_sds_dimension (sds_name);
};
/**
* @brief access the size of a vdata
* It returns a 2 values vector like this {nb of vdata records, nb of fields}. It doesn't change if the fields have an order bigger than one.
* @param vdata_name the name of the vdata
* @return a vector that contains the dimensions of the vdata.
*/
vector get_vdata_dimension(const string &vdata_name);
int get_n_dataset(){return this->get_hdf_file()->get_n_sds();};
string get_dataset_name(int i){return this->get_hdf_file()->get_sds_name(i);};
Hdf_sds get_dataset(string sds_name){return this->get_hdf_file()->get_sds(sds_name.c_str());};
int get_dataset_data_type(string sds_name)
{return this->get_hdf_file()->get_sds_data_type(sds_name.c_str());};
string get_values_attr_dataset(string sds_name,string attr_name);
bool has_attr_dataset(string sds_name,string attr_name);
/**
* @brief closes the file
*/
void close_data_file(){free_hdf_file();};
/**
* @brief open the file
*/
void open_data_file(){load_hdf_file();};
string get_values_attr(string attr_name);
string get_file_attr(string attr_name);
bool has_attr(string attr_name);
bool has_file_attr(string attr_name);
/************************
** DATA ACCESS METHODS **
************************/
/**
Read a value in a sds directly using its y_index and x_index. This method is a convenience method to access to a 2D sds.
This method is a template, so you have also to precise the data type of the read value while calling it.
Ex :
float32 v = get_var_value("Latitude",12,1);
will read in the sds "Latitude" the value at (12,1) using (Y,X) convention
@return the read value
*/
template
T get_var_value(const string sds_name, const int &y_index,const int &x_index);
/**
In the opened file, read the value of the sds called "sds_name" at the point "start". BE CAREFUL : this array must be given using the order ...[Z][Y][X].
This method is a template, so you have also to precise the data type of the read value while calling it.
If you are trying to read a value in a 2D sds, please refer to the get_var_value method. It's a simplest front-end to this method.
An examples is clearest :
long start[] = {16,25}; // start position
long rank = 2; // the dimension of start
float32 val = hfd.get_value_0D("Latitude",start,NULL,NULL,rank);
It will read the data of the sds "Latitude", that is composed of float32 values at the position (16,25) using (Y,X) convention (ie (lat,lon)).
@param sds_name the name of the sds (Scientific Data Set) we want to access.
@param start begining of the selection. If NULL, start at (0,0) if rank is 2 ; (0,0,0) if rank is 3...
@param stride step between 2 interesting values. If NULL, this step is set to 1 in each dimension (ie all values will be read)
@param edges number of values to be read in each dimension. if NULL, it will be all data along each dimension.
@param rank the dimension of start
@return a pointer to a 1D vector containing the selected values of type T. Allocated with new inside, and so must be deleted by the caller after being used.
*/
template
T get_value_0D( const char * sds_name = "Height", int *start = NULL, int *stride = NULL, int *edges = NULL, int &rank = -1);
/**
In the opened file, read the values of the sds called "sds_name", starting at the point "start", reading "edges" values, with a step of "stride" between each values. BE CAREFUL : those array values must be given using the order ...[Z][Y][X].
The result data must be a 1D array. If it isn't the case, an error message will prevent you.
This method is a template, so you have also to precise the data type of the read values while calling it.
Some examples are clearest :
----------------------------- EXAMPLE 1 ----------------------------
long start[] = {3,0}; // start position
long stride[] = {2,1}; // step between 2 values
long edges[] = {35,1}; // number of values to be read
long rank = 2; // the dimension of start,stride and edges
vector *v = hfd.get_value_1D("Latitude",start,stride,edges,rank);
It will read the data of the sds "Latitude", that is composed of float32 values.
- Along X, 1 value (edges[1]) will be read, starting at the position 0 (start[1]), with a step of 1 (stride[1]) between 2 values. In this case, the step isn't useful because we read only 1 value.
- Along Y, 35 values (edges[0]) will be read, starting at the position 3 (start[0]), with a step of 2 (stride[0]) between 2 values.
The method will return a POINTER to an 1D vector. So, to access the read data, use (*v)[0] instead of v[0] if it wasn't a pointer.
----------------------------- EXAMPLE 2 ----------------------------
long start[] = {0,0,0}; // start position
long stride[] = {1,1,1}; // same result if NULL, and even a little bit faster : by default, the step between 2 values is 1
long edges[] = {20,1,1}; // number of values to be read
long rank = 3; // the dimension of start,stride and edges
vector *v = hfd.get_value_1D("Nb_Layer_Found",start,stride,edges,rank);
It will read the data of the sds "Nb_Layer_Found", that is composed of uint8 values.
- Along X, 1 value (edges[2]) will be read, starting at the position 0 (start[2]), with a step of 1 (stride[2]).
- Along Y, 1 values (edges[1]) will be read, starting at the position 0 (start[1]), with a step of 1 (stride[1]).
- Along Z, 20 values (edges[0]) will be read, starting at the position 0 (start[0]), with a step of 1 (stride[0]).
The method will return a POINTER to an 1D vector.
TODO----------------------------- EXAMPLE 3 : USING DEFAULT VALUES (not available yet) ----------------------------
TODO
vector *v = get_value_1D("Top_Layer_Height",NULL,NULL,NULL,1);
TODO It will return the whole data of type float32 contained in the sds named "Top_Layer_Height".
TODO REM : In this case, the sds "Top_Layer_Height" must have a dimension of 1, because the read values' vector must have a dimension of 1.
@param sds_name the name of the sds (Scientific Data Set) we want to access.
@param start begining of the selection. If NULL, start at (0,0) if rank is 2 ; (0,0,0) if rank is 3...
@param stride step between 2 interesting values. If NULL, this step is set to 1 in each dimension (ie all values will be read)
@param edges number of values to be read in each dimension. if NULL, it will be all data along each dimension.
@param rank the dimension of start, stride and edges
@return a pointer to a 1D vector containing the selected values of type T. Allocated with new inside, and so must be deleted by the caller after being used.
*/
template
vector *get_value_1D( const char * sds_name = "Height", int *start = NULL, int *stride = NULL, int *edges = NULL, int &rank= -1);
/**
In the opened file, read the values of the sds called "sds_name", starting at the point "start", reading "edges" values, with a step of "stride" between each values. BE CAREFUL : those array values must be given using the order ...[Z][Y][X].
The result data must be a 1D array. If it isn't the case, an error message will prevent you.
This method is a template, so you have also to precise the data type of the read values while calling it.
Some examples are clearest :
----------------------------- EXAMPLE 1 ----------------------------
long start[] = {3,0}; // start position
long stride[] = {2,1}; // step between 2 values
long edges[] = {35,2}; // number of values to be read
long rank = 2; // the dimension of start,stride and edges
vector *v = hfd.get_value_2D("Latitude",start,stride,edges,rank);
It will read the data of the sds "Latitude", that is composed of float32 values.
- Along X, 2 value (edges[1]) will be read, starting at the position 0 (start[1]), with a step of 1 (stride[1]) between 2 values.
- Along Y, 35 values (edges[0]) will be read, starting at the position 3 (start[0]), with a step of 2 (stride[0]) between 2 values.
The method will return a POINTER to an 2D vector. So, to access the read data, use (*v)[0][0].
----------------------------- EXAMPLE 2 ----------------------------
long start[] = {0,0,0}; // start position
long stride[] = {1,1,1}; // same result if NULL, and even a little bit faster : by default, the step between 2 values is 1
long edges[] = {1,20,15}; // number of values to be read
long rank = 3; // the dimension of start,stride and edges
vector *v = hfd.get_value_2D("Nb_Layer_Found",start,stride,edges,rank);
It will read the data of the sds "Nb_Layer_Found", that is composed of uint8 values.
- Along X (the longitude for ex), 15 values (edges[2]) will be read, starting at the position 0 (start[2]), with a step of 1 (stride[2]).
- Along Y (the latitude for ex), 20 values (edges[1]) will be read, starting at the position 0 (start[1]), with a step of 1 (stride[1]).
- Along Z (the number of layers found for ex), 1 value (edges[0]) will be read, starting at the position 0 (start[0]), with a step of 1 (stride[0]).
The method will return a POINTER to an 2D vector.
In this example, the sense of the return vector will be : the number of cloud's layers found along (20,15) lat_lon mesures.
TODO----------------------------- EXAMPLE 3 : USING DEFAULT VALUES (not available yet) ----------------------------
TODO
vector *v = get_value_2D("Longitude",NULL,NULL,NULL,2);
TODO It will return the whole data of type float32 contained in the sds named "Longitude".
TODO REM : In this case, the sds "Longitude" must have a dimension of 2, because the read values' vector must have a dimension of 2.
@param sds_name the name of the sds (Scientific Data Set) we want to access.
@param start begining of the selection. If NULL, start at (0,0) if rank is 2 ; (0,0,0) if rank is 3...
@param stride step between 2 interesting values. If NULL, this step is set to 1 in each dimension (ie all values will be read)
@param edges number of values to be read in each dimension. if NULL, it will be all data along each dimension.
@param rank the dimension of start, stride and edges
@return a pointer to a 2D vector containing the selected values of type T. Allocated with new inside, and so must be deleted by the caller after being used.
*/
template
vector< vector >* get_value_2D( const char * sds_name = "Height", int *start = NULL, int *stride = NULL, int *edges = NULL, int &rank=-1);
/**
Read the data in a HDF file. Similar to get_value_nD methods, but in a C way : this method fills an array and doesn't use a std::vector.
Some examples are clearest :
----------------------------- EXAMPLE 1 ----------------------------
long Y_LENGTH = 2;
long X_LENGTH = 35;
long start[] = {3,0}; // start position
long stride[] = {2,1}; // step between 2 values
long edges[] = {X_LENGTH,Y_LENGTH}; // number of values to be read
long rank = 2; // the dimension of start,stride and edges
float32 data[Y_LENGTH][X_LENGTH]; // buffer where to put the read data
hfd.read_data((void*)data,"Latitude",start,stride,edges,rank);
It will read the data of the sds "Latitude", that is composed of float32 values.
- Along X, 2 value (edges[1]) will be read, starting at the position 0 (start[1]), with a step of 1 (stride[1]) between 2 values.
- Along Y, 35 values (edges[0]) will be read, starting at the position 3 (start[0]), with a step of 2 (stride[0]) between 2 values.
----------------------------- EXAMPLE 2 ----------------------------
long Z_LENGTH = 1;
long Y_LENGTH = 20;
long X_LENGTH = 15;
long start[] = {0,0,0}; // start position
long stride[] = {1,1,1}; // same result if NULL, and even a little bit faster : by default, the step between 2 values is 1
long edges[] = {Z_LENGTH,Y_LENGTH,X_LENGTH}; // number of values to be read
long rank = 3; // the dimension of start,stride and edges
uint8 data[Z_LENGTH][Y_LENGTH][X_LENGTH]; // buffer where to put the read data
hfd.read_data((void*)data,"Nb_Layer_Found",start,stride,edges,rank);
It will read the data of the sds "Nb_Layer_Found", that is composed of uint8 values.
- Along X (the longitude for ex), 15 values (edges[2]) will be read, starting at the position 0 (start[2]), with a step of 1 (stride[2]).
- Along Y (the latitude for ex), 20 values (edges[1]) will be read, starting at the position 0 (start[1]), with a step of 1 (stride[1]).
- Along Z (the number of layers found for ex), 1 value (edges[0]) will be read, starting at the position 0 (start[0]), with a step of 1 (stride[0]).
----------------------------- EXAMPLE 3 : USING DEFAULT VALUES ----------------------------
float32 *data = NULL; // buffer where to put the read data
data=(float32*)hfd.read_data((void*)data,"Longitude");// the method allocates the needed memory
// Do what you have to do with data here
delete[] data;// Don't forget to free the memory once used
It will read the whole data of type float32 contained in the sds named "Longitude". The method manages the allocation of the data' array
@param data the buffer to fill with the read values
@param sds_name the name of the sds (Scientific Data Set) we want to access.
@param start begining of the selection. If NULL, start at (0,0) if rank is 2 ; (0,0,0) if rank is 3...
@param stride step between 2 interesting values. If NULL, this step is set to 1 in each dimension (ie all values will be read)
@param edges number of values to be read in each dimension. if NULL, it will be all data along each dimension.
@param rank the dimension of start, stride and edges
@return a pointer to the read data array. It is useful when you let this method manage the allocation to update the allocated pointer to the data. If you've done it yourself or you are using a static buffer, it isn't necessary to catch this return pointer
*/
virtual void * read_data(void * data, const char * sds_name, int * start = NULL, int * stride = NULL, int * edges = NULL, int rank = -1);
/**
* @brief method to read the data of an sds similar to void* read_data(...)
* This method add a test on the validity of the ouput buffer type compared to the sds one.
* @warning this method can only be used with 1D output buffers (you can use an indexation like [j*nb_i+i] to simulate a 2D buffer )
* @param data
* @param sds_name
* @param start
* @param stride
* @param edges
* @param rank
* @return
*/
template
DataType * read_data(DataType * data, const char * sds_name, int * start = NULL, int * stride = NULL, int * edges = NULL, int rank = -1);
/**
* @brief read the data of an hdf VData Field
* - for a multi_order field, all order will be loaded. See the HDF documentation for more details about it.
----------------------------- USING DEFAULT VALUES ----------------------------
Like the read_data method, you can use the default values to read all the data.
Nevertheless, some precautions have to be taken if you let the method do the allocation (ie data parametre is NULL)
- Set your data buffer to the return value of the method to update its adress
- Don't forget to delete the data buffer once used using the delete[] operator
Here is a example :
float32 *data = NULL; // buffer where to put the read data. Set it to NULL to let the method allocate it
data=(float32)hfd.read_vdata((VOIDP)data,"Longitude");// the method allocates the needed memory. Remark that data s set to the method's return value. It works in a malloc way. That's why you also have to cast it
// Do what you have to do with data
delete[] data;// Don't forget to free the memory once used
* @param data the data buffer. Can be NULL. In this case, the allocation is done by the method. In this case, the caller MUST delete the buffer once
* @param vdata_name the name of the VData
* @param vdata_field the name of the field
* @param start the start point. default : 0 : the record start
* @param edges the number of values to read in all direction. If -1 (default), will read all records
* @return a pointer to the buffer. Useful only if the dynamic allocation is done by the method
*
*/
void* read_vdata(void* data,const char* vdata_name="", const char* vdata_field="", int start=0, int edges=-1);
/**
* @brief read the given dataset's fill value
* @param ds_name [IN] dataset name
* @param fillvalue [OUT] fill value.
*/
void get_fillValue(const string &sds_name, void *fillValue);
void get_scaling(const string &sds_name, float64 &scale, float64 &offset);
};
/*************************************************/
/************ TEMPLATES DEFINITION ***************/
/*************************************************/
template
T* HDFFileData::get_value( const char * sds_name, int *start, int *stride, int *edges, int rank) {
bool are_limits_initialized[3]; // check if start, stride or edges had been initialized in this method
bool hdf_file_already_loaded = is_hdf_file_loaded();
try {
if (!hdf_file_already_loaded)
load_hdf_file();
// --- initialize NULL input parametres ---
init_read_write_null_input_param(sds_name, start, stride, edges,rank, are_limits_initialized);
// check the selection limits
check_read_write_limits(sds_name, start,stride,edges,rank); // throw bad_index in case of problem
// check if there is a conflict between the template type and the sds type
if ( typeid(T).name() != Hdf_common::hdf_type_info(hdf_file->get_sds_data_type(sds_name)) ) {
bad_type e(Hdf_common::hdf_type_info(hdf_file->get_sds_data_type(sds_name)),typeid(T).name(),sds_name);
throw e;
}
// allocate a buffer to read the data
int data_size = 1;
for (int i = 0 ; iread_sds(sds_name,hdf_data,(int32*)start,(int32*)stride,(int32*)edges);
// free the ressources allocated by this method
free_read_write_allocations(are_limits_initialized, start, stride, edges);
if (!hdf_file_already_loaded)
free_hdf_file();
return (hdf_data);
} catch(...) {
// free the ressources allocated in this method
free_read_write_allocations(are_limits_initialized , start, stride,edges);
throw;
}
};
template
T HDFFileData::get_value_0D( const char * sds_name, int *start, int *stride, int *edges, int &rank ) {
T* data = get_value(sds_name,start,stride,edges,rank);
T ret=(*data);
delete[] data;
return ret;
}
template
vector *HDFFileData::get_value_1D( const char * sds_name, int *start, int *stride, int *edges, int &rank) {
// specific to the method
int method_rank = 1;
// read the values in a linear buffer
T* data = get_value(sds_name,start,stride,edges,rank);
// initialize the return vector size
int significant_edges_index[method_rank]; // the index of the edges > 1
int dim_size[method_rank]; // size of the edges > 1
int dim_size_to_init_index = 0;
for (int i=0 ; i1) {
dim_size[dim_size_to_init_index]=edges[i];
significant_edges_index[dim_size_to_init_index]=i;
++dim_size_to_init_index;
}
}
// allocate the vector
vector *v_data = new vector ; // format to return : easier and faster to process
v_data->reserve(dim_size[0]);
// put the data in the vector : easier and faster to process
for ( int i = 0 ; i < dim_size[0] ; ++i ) {
v_data->push_back(data[i]);
}
delete[] data;
return v_data;
}
template
vector< vector >* HDFFileData::get_value_2D( const char * sds_name , int *start, int *stride, int *edges, int &rank) {
// rank specific to the method
int method_rank = 2;
// read the values in a linear buffer
T* data = get_value(sds_name,start,stride,edges,rank);
// initialize the return vector size
int significant_edges_index[method_rank]; // the index of the edges > 1
int dim_size[method_rank]; // size of the edges > 1
int dim_size_to_init_index = 0;
for (int i=0 ; i1) {
dim_size[dim_size_to_init_index]=edges[i];
significant_edges_index[dim_size_to_init_index]=i;
++dim_size_to_init_index;
}
}
// allocate the vector
vector< vector > *v_data = new vector< vector >; // format to return : easier and faster to process
v_data->reserve(dim_size[0]);
// put the data in the vector : easier and faster to process
for ( int i = 0 ; i < dim_size[0] ; ++i ) {
vector tmp;
for ( int j = 0 ; j < dim_size[1] ; ++j )
tmp.push_back(data[i*dim_size[1]+j]);
v_data->push_back(tmp);
}
delete[] data;
return v_data;
}
template
T HDFFileData::get_var_value(const string var_name, const int &y_index,const int &x_index) {
int start[]={y_index,x_index};
int edges[]={1,1};
int rank=2;
return get_value_0D(var_name.c_str(),start,NULL,edges,rank);
}
template
const vector HDFFileData::get_nearest_index(const vector &v_data, const T &val) {
vector ret;
if (!v_data.empty()) {
T diff = abs((v_data[0])-val);
T current_diff; // temporary difference -> faster
int end = v_data.size();
for (int i = 0; i
const int HDFFileData::get_nearest_index(const vector *data, const T val) {
int nearest_val_index=-1;
T nearest_value;
T delta;
if (!data->empty()) {
int length = data->size();
nearest_val_index=0;
nearest_value=(*data)[nearest_val_index];
delta=abs(val-nearest_value);
for (int i = 1 ; i
const int HDFFileData::get_nearest_index(const T *data, const int data_size, const T val) {
int nearest_val_index=-1;
T nearest_value;
T delta;
if (data!=NULL && data_size!=0) {
nearest_val_index=0;
nearest_value=*(data+nearest_val_index);
delta=abs(val-nearest_value);
for (int i = 1 ; i
T * HDFFileData::read_data(T * data, const char * sds_name, int * start, int * stride, int * edges, int rank ) {
bool are_limits_initialized[3]; // check if start, stride or edges had been initialized in this method
bool hdf_file_already_loaded = is_hdf_file_loaded();
try {
if (!hdf_file_already_loaded)
load_hdf_file();
// --- initialize NULL input parametres ---
init_read_write_null_input_param(sds_name,start,stride,edges,rank,are_limits_initialized);
// check the selection limits
check_read_write_limits(sds_name,start,stride,edges,rank); // throw bad_index in case of problem
// check if DataType has the same type than the sds values
if ( typeid(T).name() != Hdf_common::hdf_type_info(hdf_file->get_sds_data_type(sds_name)) ) {
bad_type e(Hdf_common::hdf_type_info(hdf_file->get_sds_data_type(sds_name)),typeid(T).name(),sds_name);
throw e;
}
// read the desired value, in the good format
int data_size = 1;
for (int i = 0 ; iread_sds(sds_name,data,(int32*)start,(int32*)stride,(int32*)edges);
// free the ressources allocated by this method
free_read_write_allocations(are_limits_initialized,start,stride,edges);
if (!hdf_file_already_loaded)
free_hdf_file();
return data;
} catch(...) {
free_read_write_allocations(are_limits_initialized,start,stride,edges);
throw;
}
}
#endif